forked from quickshell/quickshell
		
	tooling: add automatic QMLLS support for new imports and singletons
This commit is contained in:
		
							parent
							
								
									4d8055f1cd
								
							
						
					
					
						commit
						986749cdb9
					
				
					 7 changed files with 283 additions and 3 deletions
				
			
		| 
						 | 
					@ -38,6 +38,7 @@ qt_add_library(quickshell-core STATIC
 | 
				
			||||||
	iconprovider.cpp
 | 
						iconprovider.cpp
 | 
				
			||||||
	scriptmodel.cpp
 | 
						scriptmodel.cpp
 | 
				
			||||||
	colorquantizer.cpp
 | 
						colorquantizer.cpp
 | 
				
			||||||
 | 
						toolsupport.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qt_add_qml_module(quickshell-core
 | 
					qt_add_qml_module(quickshell-core
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,33 @@ QDir* QsPaths::instanceRunDir() {
 | 
				
			||||||
	else return &this->mInstanceRunDir;
 | 
						else return &this->mInstanceRunDir;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QDir* QsPaths::shellVfsDir() {
 | 
				
			||||||
 | 
						if (this->shellVfsState == DirState::Unknown) {
 | 
				
			||||||
 | 
							if (auto* baseRunDir = this->baseRunDir()) {
 | 
				
			||||||
 | 
								this->mShellVfsDir = QDir(baseRunDir->filePath("vfs"));
 | 
				
			||||||
 | 
								this->mShellVfsDir = QDir(this->mShellVfsDir.filePath(this->shellId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								qCDebug(logPaths) << "Initialized runtime vfs path:" << this->mShellVfsDir.path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!this->mShellVfsDir.mkpath(".")) {
 | 
				
			||||||
 | 
									qCCritical(logPaths) << "Could not create runtime vfs directory at"
 | 
				
			||||||
 | 
									                     << this->mShellVfsDir.path();
 | 
				
			||||||
 | 
									this->shellVfsState = DirState::Failed;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									this->shellVfsState = DirState::Ready;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qCCritical(logPaths) << "Could not create shell runtime vfs path as it was not possible to "
 | 
				
			||||||
 | 
								                        "create the base runtime path.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this->shellVfsState = DirState::Failed;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->shellVfsState == DirState::Failed) return nullptr;
 | 
				
			||||||
 | 
						else return &this->mShellVfsDir;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void QsPaths::linkRunDir() {
 | 
					void QsPaths::linkRunDir() {
 | 
				
			||||||
	if (auto* runDir = this->instanceRunDir()) {
 | 
						if (auto* runDir = this->instanceRunDir()) {
 | 
				
			||||||
		auto pidDir = QDir(this->baseRunDir()->filePath("by-pid"));
 | 
							auto pidDir = QDir(this->baseRunDir()->filePath("by-pid"));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QDir* baseRunDir();
 | 
						QDir* baseRunDir();
 | 
				
			||||||
	QDir* shellRunDir();
 | 
						QDir* shellRunDir();
 | 
				
			||||||
 | 
						QDir* shellVfsDir();
 | 
				
			||||||
	QDir* instanceRunDir();
 | 
						QDir* instanceRunDir();
 | 
				
			||||||
	void linkRunDir();
 | 
						void linkRunDir();
 | 
				
			||||||
	void linkPathDir();
 | 
						void linkPathDir();
 | 
				
			||||||
| 
						 | 
					@ -48,9 +49,11 @@ private:
 | 
				
			||||||
	QString pathId;
 | 
						QString pathId;
 | 
				
			||||||
	QDir mBaseRunDir;
 | 
						QDir mBaseRunDir;
 | 
				
			||||||
	QDir mShellRunDir;
 | 
						QDir mShellRunDir;
 | 
				
			||||||
 | 
						QDir mShellVfsDir;
 | 
				
			||||||
	QDir mInstanceRunDir;
 | 
						QDir mInstanceRunDir;
 | 
				
			||||||
	DirState baseRunState = DirState::Unknown;
 | 
						DirState baseRunState = DirState::Unknown;
 | 
				
			||||||
	DirState shellRunState = DirState::Unknown;
 | 
						DirState shellRunState = DirState::Unknown;
 | 
				
			||||||
 | 
						DirState shellVfsState = DirState::Unknown;
 | 
				
			||||||
	DirState instanceRunState = DirState::Unknown;
 | 
						DirState instanceRunState = DirState::Unknown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QDir mShellDataDir;
 | 
						QDir mShellDataDir;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <qdir.h>
 | 
					#include <qdir.h>
 | 
				
			||||||
#include <qfileinfo.h>
 | 
					#include <qfileinfo.h>
 | 
				
			||||||
 | 
					#include <qfilesystemwatcher.h>
 | 
				
			||||||
#include <qlogging.h>
 | 
					#include <qlogging.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qqmlcomponent.h>
 | 
					#include <qqmlcomponent.h>
 | 
				
			||||||
| 
						 | 
					@ -18,15 +19,26 @@
 | 
				
			||||||
#include "instanceinfo.hpp"
 | 
					#include "instanceinfo.hpp"
 | 
				
			||||||
#include "qmlglobal.hpp"
 | 
					#include "qmlglobal.hpp"
 | 
				
			||||||
#include "scan.hpp"
 | 
					#include "scan.hpp"
 | 
				
			||||||
 | 
					#include "toolsupport.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RootWrapper::RootWrapper(QString rootPath, QString shellId)
 | 
					RootWrapper::RootWrapper(QString rootPath, QString shellId)
 | 
				
			||||||
    : QObject(nullptr)
 | 
					    : QObject(nullptr)
 | 
				
			||||||
    , rootPath(std::move(rootPath))
 | 
					    , rootPath(std::move(rootPath))
 | 
				
			||||||
    , shellId(std::move(shellId))
 | 
					    , shellId(std::move(shellId))
 | 
				
			||||||
    , originalWorkingDirectory(QDir::current().absolutePath()) {
 | 
					    , originalWorkingDirectory(QDir::current().absolutePath()) {
 | 
				
			||||||
	// clang-format off
 | 
						QObject::connect(
 | 
				
			||||||
	QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &RootWrapper::onWatchFilesChanged);
 | 
						    QuickshellSettings::instance(),
 | 
				
			||||||
	// clang-format on
 | 
						    &QuickshellSettings::watchFilesChanged,
 | 
				
			||||||
 | 
						    this,
 | 
				
			||||||
 | 
						    &RootWrapper::onWatchFilesChanged
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(
 | 
				
			||||||
 | 
						    &this->configDirWatcher,
 | 
				
			||||||
 | 
						    &QFileSystemWatcher::directoryChanged,
 | 
				
			||||||
 | 
						    this,
 | 
				
			||||||
 | 
						    &RootWrapper::updateTooling
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->reloadGraph(true);
 | 
						this->reloadGraph(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +60,9 @@ void RootWrapper::reloadGraph(bool hard) {
 | 
				
			||||||
	auto scanner = QmlScanner(rootPath);
 | 
						auto scanner = QmlScanner(rootPath);
 | 
				
			||||||
	scanner.scanQmlFile(this->rootPath);
 | 
						scanner.scanQmlFile(this->rootPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qs::core::QmlToolingSupport::updateTooling(rootPath, scanner);
 | 
				
			||||||
 | 
						this->configDirWatcher.addPath(rootPath.path());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto* generation = new EngineGeneration(rootPath, std::move(scanner));
 | 
						auto* generation = new EngineGeneration(rootPath, std::move(scanner));
 | 
				
			||||||
	generation->wrapper = this;
 | 
						generation->wrapper = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,3 +183,9 @@ void RootWrapper::onWatchFilesChanged() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RootWrapper::onWatchedFilesChanged() { this->reloadGraph(false); }
 | 
					void RootWrapper::onWatchedFilesChanged() { this->reloadGraph(false); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RootWrapper::updateTooling() {
 | 
				
			||||||
 | 
						if (!this->generation) return;
 | 
				
			||||||
 | 
						auto configDir = QFileInfo(this->rootPath).dir();
 | 
				
			||||||
 | 
						qs::core::QmlToolingSupport::updateTooling(configDir, this->generation->scanner);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qfilesystemwatcher.h>
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qqmlengine.h>
 | 
					#include <qqmlengine.h>
 | 
				
			||||||
#include <qtclasshelpermacros.h>
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
| 
						 | 
					@ -22,10 +23,12 @@ private slots:
 | 
				
			||||||
	void generationDestroyed();
 | 
						void generationDestroyed();
 | 
				
			||||||
	void onWatchFilesChanged();
 | 
						void onWatchFilesChanged();
 | 
				
			||||||
	void onWatchedFilesChanged();
 | 
						void onWatchedFilesChanged();
 | 
				
			||||||
 | 
						void updateTooling();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	QString rootPath;
 | 
						QString rootPath;
 | 
				
			||||||
	QString shellId;
 | 
						QString shellId;
 | 
				
			||||||
	EngineGeneration* generation = nullptr;
 | 
						EngineGeneration* generation = nullptr;
 | 
				
			||||||
	QString originalWorkingDirectory;
 | 
						QString originalWorkingDirectory;
 | 
				
			||||||
 | 
						QFileSystemWatcher configDirWatcher;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										205
									
								
								src/core/toolsupport.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								src/core/toolsupport.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,205 @@
 | 
				
			||||||
 | 
					#include "toolsupport.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qcontainerfwd.h>
 | 
				
			||||||
 | 
					#include <qdebug.h>
 | 
				
			||||||
 | 
					#include <qdir.h>
 | 
				
			||||||
 | 
					#include <qfileinfo.h>
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qloggingcategory.h>
 | 
				
			||||||
 | 
					#include <qnamespace.h>
 | 
				
			||||||
 | 
					#include <qtenvironmentvariables.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "logcat.hpp"
 | 
				
			||||||
 | 
					#include "paths.hpp"
 | 
				
			||||||
 | 
					#include "scan.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::core {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					QS_LOGGING_CATEGORY(logTooling, "quickshell.tooling", QtWarningMsg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool QmlToolingSupport::updateTooling(const QDir& configRoot, QmlScanner& scanner) {
 | 
				
			||||||
 | 
						auto* vfs = QsPaths::instance()->shellVfsDir();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vfs) {
 | 
				
			||||||
 | 
							qCCritical(logTooling) << "Tooling dir could not be created";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!QmlToolingSupport::updateQmllsConfig(configRoot, false)) {
 | 
				
			||||||
 | 
							QDir(vfs->filePath("qs")).removeRecursively();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QmlToolingSupport::updateToolingFs(scanner, configRoot, vfs->filePath("qs"));
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString QmlToolingSupport::getQmllsConfig() {
 | 
				
			||||||
 | 
						static auto config = []() {
 | 
				
			||||||
 | 
							QList<QString> importPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto addPaths = [&](const QList<QString>& paths) {
 | 
				
			||||||
 | 
								for (const auto& path: paths) {
 | 
				
			||||||
 | 
									if (!importPaths.contains(path)) importPaths.append(path);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							addPaths(qEnvironmentVariable("QML_IMPORT_PATH").split(u':', Qt::SkipEmptyParts));
 | 
				
			||||||
 | 
							addPaths(qEnvironmentVariable("QML2_IMPORT_PATH").split(u':', Qt::SkipEmptyParts));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto vfsPath = QsPaths::instance()->shellVfsDir()->path();
 | 
				
			||||||
 | 
							auto importPathsStr = importPaths.join(u':');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							QString qmllsConfig;
 | 
				
			||||||
 | 
							auto print = QDebug(&qmllsConfig).nospace();
 | 
				
			||||||
 | 
							print << "[General]\nno-cmake-calls=true\nbuildDir=" << vfsPath
 | 
				
			||||||
 | 
							      << "\nimportPaths=" << importPathsStr << '\n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return qmllsConfig;
 | 
				
			||||||
 | 
						}();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return config;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool QmlToolingSupport::updateQmllsConfig(const QDir& configRoot, bool create) {
 | 
				
			||||||
 | 
						auto shellConfigPath = configRoot.filePath(".qmlls.ini");
 | 
				
			||||||
 | 
						auto vfsConfigPath = QsPaths::instance()->shellVfsDir()->filePath(".qmlls.ini");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto shellFileInfo = QFileInfo(shellConfigPath);
 | 
				
			||||||
 | 
						if (!create && !shellFileInfo.exists()) {
 | 
				
			||||||
 | 
							if (QmlToolingSupport::toolingEnabled) {
 | 
				
			||||||
 | 
								qInfo() << "QML tooling support disabled";
 | 
				
			||||||
 | 
								QmlToolingSupport::toolingEnabled = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							QFile::remove(vfsConfigPath);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto vfsFile = QFile(vfsConfigPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vfsFile.open(QFile::ReadWrite | QFile::Text)) {
 | 
				
			||||||
 | 
							qCCritical(logTooling) << "Failed to create qmlls config in vfs";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto config = QmlToolingSupport::getQmllsConfig();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vfsFile.readAll() != config) {
 | 
				
			||||||
 | 
							if (!vfsFile.resize(0) || !vfsFile.write(config.toUtf8())) {
 | 
				
			||||||
 | 
								qCCritical(logTooling) << "Failed to write qmlls config in vfs";
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							qCDebug(logTooling) << "Wrote qmlls config in vfs";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!shellFileInfo.isSymLink() || shellFileInfo.symLinkTarget() != vfsConfigPath) {
 | 
				
			||||||
 | 
							QFile::remove(shellConfigPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!QFile::link(vfsConfigPath, shellConfigPath)) {
 | 
				
			||||||
 | 
								qCCritical(logTooling) << "Failed to create qmlls config symlink";
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							qCDebug(logTooling) << "Created qmlls config symlink";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!QmlToolingSupport::toolingEnabled) {
 | 
				
			||||||
 | 
							qInfo() << "QML tooling support enabled";
 | 
				
			||||||
 | 
							QmlToolingSupport::toolingEnabled = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void QmlToolingSupport::updateToolingFs(
 | 
				
			||||||
 | 
					    QmlScanner& scanner,
 | 
				
			||||||
 | 
					    const QDir& scanDir,
 | 
				
			||||||
 | 
					    const QDir& linkDir
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						QList<QString> files;
 | 
				
			||||||
 | 
						QSet<QString> subdirs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto scanPath = scanDir.path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						linkDir.mkpath(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto& path: scanner.scannedFiles) {
 | 
				
			||||||
 | 
							if (path.length() < scanPath.length() + 1 || !path.startsWith(scanPath)) continue;
 | 
				
			||||||
 | 
							auto name = path.sliced(scanPath.length() + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (name.contains('/')) {
 | 
				
			||||||
 | 
								auto dirname = name.first(name.indexOf('/'));
 | 
				
			||||||
 | 
								subdirs.insert(dirname);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto fileInfo = QFileInfo(path);
 | 
				
			||||||
 | 
							if (!fileInfo.isFile()) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto spath = linkDir.filePath(name);
 | 
				
			||||||
 | 
							auto sFileInfo = QFileInfo(spath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!sFileInfo.isSymLink() || sFileInfo.symLinkTarget() != path) {
 | 
				
			||||||
 | 
								QFile::remove(spath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (QFile::link(path, spath)) {
 | 
				
			||||||
 | 
									qCDebug(logTooling) << "Created symlink to" << path << "at" << spath;
 | 
				
			||||||
 | 
									files.append(spath);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									qCCritical(logTooling) << "Could not create symlink to" << path << "at" << spath;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								files.append(spath);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto [path, text]: scanner.fileIntercepts.asKeyValueRange()) {
 | 
				
			||||||
 | 
							if (path.length() < scanPath.length() + 1 || !path.startsWith(scanPath)) continue;
 | 
				
			||||||
 | 
							auto name = path.sliced(scanPath.length() + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (name.contains('/')) {
 | 
				
			||||||
 | 
								auto dirname = name.first(name.indexOf('/'));
 | 
				
			||||||
 | 
								subdirs.insert(dirname);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto spath = linkDir.filePath(name);
 | 
				
			||||||
 | 
							auto file = QFile(spath);
 | 
				
			||||||
 | 
							if (!file.open(QFile::ReadWrite | QFile::Text)) {
 | 
				
			||||||
 | 
								qCCritical(logTooling) << "Failed to open injected file" << spath;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (file.readAll() == text) {
 | 
				
			||||||
 | 
								files.append(spath);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (file.resize(0) && file.write(text.toUtf8())) {
 | 
				
			||||||
 | 
								files.append(spath);
 | 
				
			||||||
 | 
								qCDebug(logTooling) << "Wrote injected file" << spath;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qCCritical(logTooling) << "Failed to write injected file" << spath;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto& name: linkDir.entryList(QDir::Files | QDir::System)) { // System = broken symlinks
 | 
				
			||||||
 | 
							auto path = linkDir.filePath(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!files.contains(path)) {
 | 
				
			||||||
 | 
								if (QFile::remove(path)) qCDebug(logTooling) << "Removed old file at" << path;
 | 
				
			||||||
 | 
								else qCWarning(logTooling) << "Failed to remove old file at" << path;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (const auto& subdir: subdirs) {
 | 
				
			||||||
 | 
							QmlToolingSupport::updateToolingFs(scanner, scanDir.filePath(subdir), linkDir.filePath(subdir));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::core
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/core/toolsupport.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/core/toolsupport.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qdir.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "scan.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace qs::core {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QmlToolingSupport {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						static bool updateTooling(const QDir& configRoot, QmlScanner& scanner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						static QString getQmllsConfig();
 | 
				
			||||||
 | 
						static bool updateQmllsConfig(const QDir& configRoot, bool create);
 | 
				
			||||||
 | 
						static void updateToolingFs(QmlScanner& scanner, const QDir& scanDir, const QDir& linkDir);
 | 
				
			||||||
 | 
						static inline bool toolingEnabled = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace qs::core
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue