core: support qs. imports
This commit is contained in:
		
							parent
							
								
									3d594e16dd
								
							
						
					
					
						commit
						0aecd9729f
					
				
					 7 changed files with 121 additions and 35 deletions
				
			
		| 
						 | 
					@ -37,7 +37,7 @@ EngineGeneration::EngineGeneration(const QDir& rootPath, QmlScanner scanner)
 | 
				
			||||||
    : rootPath(rootPath)
 | 
					    : rootPath(rootPath)
 | 
				
			||||||
    , scanner(std::move(scanner))
 | 
					    , scanner(std::move(scanner))
 | 
				
			||||||
    , urlInterceptor(this->rootPath)
 | 
					    , urlInterceptor(this->rootPath)
 | 
				
			||||||
    , interceptNetFactory(this->scanner.fileIntercepts)
 | 
					    , interceptNetFactory(this->rootPath, this->scanner.fileIntercepts)
 | 
				
			||||||
    , engine(new QQmlEngine()) {
 | 
					    , engine(new QQmlEngine()) {
 | 
				
			||||||
	g_generations.insert(this->engine, this);
 | 
						g_generations.insert(this->engine, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,8 @@ EngineGeneration::EngineGeneration(const QDir& rootPath, QmlScanner scanner)
 | 
				
			||||||
	QObject::connect(this->engine, &QQmlEngine::warnings, this, &EngineGeneration::onEngineWarnings);
 | 
						QObject::connect(this->engine, &QQmlEngine::warnings, this, &EngineGeneration::onEngineWarnings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->engine->addUrlInterceptor(&this->urlInterceptor);
 | 
						this->engine->addUrlInterceptor(&this->urlInterceptor);
 | 
				
			||||||
 | 
						this->engine->addImportPath("qs:/");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->engine->setNetworkAccessManagerFactory(&this->interceptNetFactory);
 | 
						this->engine->setNetworkAccessManagerFactory(&this->interceptNetFactory);
 | 
				
			||||||
	this->engine->setIncubationController(&this->delayedIncubationController);
 | 
						this->engine->setIncubationController(&this->delayedIncubationController);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -322,9 +324,11 @@ void EngineGeneration::incubationControllerDestroyed() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EngineGeneration::onEngineWarnings(const QList<QQmlError>& warnings) const {
 | 
					void EngineGeneration::onEngineWarnings(const QList<QQmlError>& warnings) {
 | 
				
			||||||
	for (const auto& error: warnings) {
 | 
						for (const auto& error: warnings) {
 | 
				
			||||||
		auto rel = "**/" % this->rootPath.relativeFilePath(error.url().path());
 | 
							const auto& url = error.url();
 | 
				
			||||||
 | 
							auto rel = url.scheme() == "qs" && url.path().startsWith("/qs/") ? "@" % url.path().sliced(4)
 | 
				
			||||||
 | 
							                                                                 : url.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		QString objectName;
 | 
							QString objectName;
 | 
				
			||||||
		auto desc = error.description();
 | 
							auto desc = error.description();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ private slots:
 | 
				
			||||||
	void onFileChanged(const QString& name);
 | 
						void onFileChanged(const QString& name);
 | 
				
			||||||
	void onDirectoryChanged();
 | 
						void onDirectoryChanged();
 | 
				
			||||||
	void incubationControllerDestroyed();
 | 
						void incubationControllerDestroyed();
 | 
				
			||||||
	void onEngineWarnings(const QList<QQmlError>& warnings) const;
 | 
						static void onEngineWarnings(const QList<QQmlError>& warnings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void postReload();
 | 
						void postReload();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#include "qsintercept.hpp"
 | 
					#include "qsintercept.hpp"
 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qdir.h>
 | 
				
			||||||
#include <qhash.h>
 | 
					#include <qhash.h>
 | 
				
			||||||
#include <qiodevice.h>
 | 
					#include <qiodevice.h>
 | 
				
			||||||
#include <qlogging.h>
 | 
					#include <qlogging.h>
 | 
				
			||||||
| 
						 | 
					@ -25,27 +26,37 @@ QUrl QsUrlInterceptor::intercept(
 | 
				
			||||||
	auto url = originalUrl;
 | 
						auto url = originalUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (url.scheme() == "root") {
 | 
						if (url.scheme() == "root") {
 | 
				
			||||||
		url.setScheme("qsintercept");
 | 
							url.setScheme("qs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto path = url.path();
 | 
							auto path = url.path();
 | 
				
			||||||
		if (path.startsWith('/')) path = path.sliced(1);
 | 
							if (path.startsWith('/')) path = path.sliced(1);
 | 
				
			||||||
		url.setPath(this->configRoot.filePath(path));
 | 
							url.setPath("/qs/" % path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		qCDebug(logQsIntercept) << "Rewrote root intercept" << originalUrl << "to" << url;
 | 
							qCDebug(logQsIntercept) << "Rewrote root intercept" << originalUrl << "to" << url;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Some types such as Image take into account where they are loading from, and force
 | 
						if (url.scheme() == "qs") {
 | 
				
			||||||
	// asynchronous loading over a network. qsintercept is considered to be over a network.
 | 
							auto path = url.path();
 | 
				
			||||||
	if (type == QQmlAbstractUrlInterceptor::DataType::UrlString && url.scheme() == "qsintercept") {
 | 
					 | 
				
			||||||
		// Qt.resolvedUrl and context->resolvedUrl can use this on qml files, in which
 | 
					 | 
				
			||||||
		// case we want to keep the intercept, otherwise objects created from those paths
 | 
					 | 
				
			||||||
		// will not be able to use singletons.
 | 
					 | 
				
			||||||
		if (url.path().endsWith(".qml")) return url;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto newUrl = url;
 | 
							// We only want to handle qs* imports for the config, nothing else.
 | 
				
			||||||
		newUrl.setScheme("file");
 | 
							if (!path.startsWith("/qs/")) return QUrl("qrc:/qs-blackhole");
 | 
				
			||||||
		qCDebug(logQsIntercept) << "Rewrote intercept" << url << "to" << newUrl;
 | 
					
 | 
				
			||||||
		return newUrl;
 | 
							// Some types such as Image take into account where they are loading from, and force
 | 
				
			||||||
 | 
							// asynchronous loading over a network. qs: is considered to be over a network.
 | 
				
			||||||
 | 
							// In those cases we want to return a file:// url so asynchronous loading is not forced.
 | 
				
			||||||
 | 
							if (type == QQmlAbstractUrlInterceptor::DataType::UrlString) {
 | 
				
			||||||
 | 
								// Qt.resolvedUrl and context->resolvedUrl can use this on qml files, in which
 | 
				
			||||||
 | 
								// case we want to keep the intercept, otherwise objects created from those paths
 | 
				
			||||||
 | 
								// will not be able to use singletons.
 | 
				
			||||||
 | 
								if (path.endsWith(".qml")) return url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto newUrl = url;
 | 
				
			||||||
 | 
								newUrl.setScheme("file");
 | 
				
			||||||
 | 
								// above check asserts path starts with /qs/
 | 
				
			||||||
 | 
								newUrl.setPath(this->configRoot.filePath(path.sliced(4)));
 | 
				
			||||||
 | 
								qCDebug(logQsIntercept) << "Rewrote intercept" << url << "to" << newUrl;
 | 
				
			||||||
 | 
								return newUrl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return url;
 | 
						return url;
 | 
				
			||||||
| 
						 | 
					@ -67,10 +78,12 @@ qint64 QsInterceptDataReply::readData(char* data, qint64 maxSize) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QsInterceptNetworkAccessManager::QsInterceptNetworkAccessManager(
 | 
					QsInterceptNetworkAccessManager::QsInterceptNetworkAccessManager(
 | 
				
			||||||
 | 
					    const QDir& configRoot,
 | 
				
			||||||
    const QHash<QString, QString>& fileIntercepts,
 | 
					    const QHash<QString, QString>& fileIntercepts,
 | 
				
			||||||
    QObject* parent
 | 
					    QObject* parent
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
    : QNetworkAccessManager(parent)
 | 
					    : QNetworkAccessManager(parent)
 | 
				
			||||||
 | 
					    , configRoot(configRoot)
 | 
				
			||||||
    , fileIntercepts(fileIntercepts) {}
 | 
					    , fileIntercepts(fileIntercepts) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QNetworkReply* QsInterceptNetworkAccessManager::createRequest(
 | 
					QNetworkReply* QsInterceptNetworkAccessManager::createRequest(
 | 
				
			||||||
| 
						 | 
					@ -79,19 +92,32 @@ QNetworkReply* QsInterceptNetworkAccessManager::createRequest(
 | 
				
			||||||
    QIODevice* outgoingData
 | 
					    QIODevice* outgoingData
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
	auto url = req.url();
 | 
						auto url = req.url();
 | 
				
			||||||
	if (url.scheme() == "qsintercept") {
 | 
					
 | 
				
			||||||
 | 
						if (url.scheme() == "qs") {
 | 
				
			||||||
		auto path = url.path();
 | 
							auto path = url.path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (path.startsWith("/qs/")) path = this->configRoot.filePath(path.sliced(4));
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								qCWarning(logQsIntercept) << "Got intercept for non /qs/ path. Redirecting to qrc:/" << path;
 | 
				
			||||||
 | 
								auto fileReq = req;
 | 
				
			||||||
 | 
								url.setScheme("qrc");
 | 
				
			||||||
 | 
								fileReq.setUrl(url);
 | 
				
			||||||
 | 
								return this->QNetworkAccessManager::createRequest(op, fileReq, outgoingData);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		qCDebug(logQsIntercept) << "Got intercept for" << path << "contains"
 | 
							qCDebug(logQsIntercept) << "Got intercept for" << path << "contains"
 | 
				
			||||||
		                        << this->fileIntercepts.value(path);
 | 
							                        << this->fileIntercepts.value(path);
 | 
				
			||||||
		auto data = this->fileIntercepts.value(path);
 | 
					
 | 
				
			||||||
		if (data != nullptr) {
 | 
							if (auto data = this->fileIntercepts.value(path); !data.isEmpty()) {
 | 
				
			||||||
			return new QsInterceptDataReply(data, this);
 | 
								return new QsInterceptDataReply(data, this);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto fileReq = req;
 | 
							auto fileReq = req;
 | 
				
			||||||
		auto fileUrl = req.url();
 | 
							auto fileUrl = req.url();
 | 
				
			||||||
		fileUrl.setScheme("file");
 | 
							fileUrl.setScheme("file");
 | 
				
			||||||
 | 
							fileUrl.setPath(path);
 | 
				
			||||||
		qCDebug(logQsIntercept) << "Passing through intercept" << url << "to" << fileUrl;
 | 
							qCDebug(logQsIntercept) << "Passing through intercept" << url << "to" << fileUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fileReq.setUrl(fileUrl);
 | 
							fileReq.setUrl(fileUrl);
 | 
				
			||||||
		return this->QNetworkAccessManager::createRequest(op, fileReq, outgoingData);
 | 
							return this->QNetworkAccessManager::createRequest(op, fileReq, outgoingData);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -100,5 +126,5 @@ QNetworkReply* QsInterceptNetworkAccessManager::createRequest(
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QNetworkAccessManager* QsInterceptNetworkAccessManagerFactory::create(QObject* parent) {
 | 
					QNetworkAccessManager* QsInterceptNetworkAccessManagerFactory::create(QObject* parent) {
 | 
				
			||||||
	return new QsInterceptNetworkAccessManager(this->fileIntercepts, parent);
 | 
						return new QsInterceptNetworkAccessManager(this->configRoot, this->fileIntercepts, parent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@ class QsInterceptNetworkAccessManager: public QNetworkAccessManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	QsInterceptNetworkAccessManager(
 | 
						QsInterceptNetworkAccessManager(
 | 
				
			||||||
 | 
						    const QDir& configRoot,
 | 
				
			||||||
	    const QHash<QString, QString>& fileIntercepts,
 | 
						    const QHash<QString, QString>& fileIntercepts,
 | 
				
			||||||
	    QObject* parent = nullptr
 | 
						    QObject* parent = nullptr
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
| 
						 | 
					@ -57,15 +58,21 @@ protected:
 | 
				
			||||||
	) override;
 | 
						) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
						QDir configRoot;
 | 
				
			||||||
	const QHash<QString, QString>& fileIntercepts;
 | 
						const QHash<QString, QString>& fileIntercepts;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QsInterceptNetworkAccessManagerFactory: public QQmlNetworkAccessManagerFactory {
 | 
					class QsInterceptNetworkAccessManagerFactory: public QQmlNetworkAccessManagerFactory {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	QsInterceptNetworkAccessManagerFactory(const QHash<QString, QString>& fileIntercepts)
 | 
						QsInterceptNetworkAccessManagerFactory(
 | 
				
			||||||
	    : fileIntercepts(fileIntercepts) {}
 | 
						    const QDir& configRoot,
 | 
				
			||||||
 | 
						    const QHash<QString, QString>& fileIntercepts
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						    : configRoot(configRoot)
 | 
				
			||||||
 | 
						    , fileIntercepts(fileIntercepts) {}
 | 
				
			||||||
	QNetworkAccessManager* create(QObject* parent) override;
 | 
						QNetworkAccessManager* create(QObject* parent) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
						QDir configRoot;
 | 
				
			||||||
	const QHash<QString, QString>& fileIntercepts;
 | 
						const QHash<QString, QString>& fileIntercepts;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,8 @@ RootWrapper::~RootWrapper() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RootWrapper::reloadGraph(bool hard) {
 | 
					void RootWrapper::reloadGraph(bool hard) {
 | 
				
			||||||
	auto rootPath = QFileInfo(this->rootPath).dir();
 | 
						auto rootFile = QFileInfo(this->rootPath);
 | 
				
			||||||
 | 
						auto rootPath = rootFile.dir();
 | 
				
			||||||
	auto scanner = QmlScanner(rootPath);
 | 
						auto scanner = QmlScanner(rootPath);
 | 
				
			||||||
	scanner.scanQmlFile(this->rootPath);
 | 
						scanner.scanQmlFile(this->rootPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,9 +59,9 @@ void RootWrapper::reloadGraph(bool hard) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QDir::setCurrent(this->originalWorkingDirectory);
 | 
						QDir::setCurrent(this->originalWorkingDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto url = QUrl::fromLocalFile(this->rootPath);
 | 
						QUrl url;
 | 
				
			||||||
	// unless the original file comes from the qsintercept scheme
 | 
						url.setScheme("qs");
 | 
				
			||||||
	url.setScheme("qsintercept");
 | 
						url.setPath("/qs/" % rootFile.fileName());
 | 
				
			||||||
	auto component = QQmlComponent(generation->engine, url);
 | 
						auto component = QQmlComponent(generation->engine, url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!component.isReady()) {
 | 
						if (!component.isReady()) {
 | 
				
			||||||
| 
						 | 
					@ -69,7 +70,8 @@ void RootWrapper::reloadGraph(bool hard) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto errors = component.errors();
 | 
							auto errors = component.errors();
 | 
				
			||||||
		for (auto& error: errors) {
 | 
							for (auto& error: errors) {
 | 
				
			||||||
			auto rel = "**/" % rootPath.relativeFilePath(error.url().path());
 | 
								const auto& url = error.url();
 | 
				
			||||||
 | 
								auto rel = url.scheme() == "qs" && url.path().startsWith("/qs/") ? "@" % url.path().sliced(4) : url.toString();
 | 
				
			||||||
			auto msg = "  caused by " % rel % '[' % QString::number(error.line()) % ':'
 | 
								auto msg = "  caused by " % rel % '[' % QString::number(error.line()) % ':'
 | 
				
			||||||
			         % QString::number(error.column()) % "]: " % error.description();
 | 
								         % QString::number(error.column()) % "]: " % error.description();
 | 
				
			||||||
			errorString += '\n' % msg;
 | 
								errorString += '\n' % msg;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,6 @@ void QmlScanner::scanDir(const QString& path) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Due to the qsintercept:// protocol a qmldir is always required, even without singletons.
 | 
					 | 
				
			||||||
	if (!seenQmldir) {
 | 
						if (!seenQmldir) {
 | 
				
			||||||
		qCDebug(logQmlScanner) << "Synthesizing qmldir for directory" << path << "singletons"
 | 
							qCDebug(logQmlScanner) << "Synthesizing qmldir for directory" << path << "singletons"
 | 
				
			||||||
		                       << singletons;
 | 
							                       << singletons;
 | 
				
			||||||
| 
						 | 
					@ -55,6 +54,29 @@ void QmlScanner::scanDir(const QString& path) {
 | 
				
			||||||
		QString qmldir;
 | 
							QString qmldir;
 | 
				
			||||||
		auto stream = QTextStream(&qmldir);
 | 
							auto stream = QTextStream(&qmldir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// cant derive a module name if not in shell path
 | 
				
			||||||
 | 
							if (path.startsWith(this->rootPath.path())) {
 | 
				
			||||||
 | 
								auto end = path.sliced(this->rootPath.path().length());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// verify we have a valid module name.
 | 
				
			||||||
 | 
								for (auto& c: end) {
 | 
				
			||||||
 | 
									if (c == '/') c = '.';
 | 
				
			||||||
 | 
									else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
 | 
				
			||||||
 | 
									         || c == '_')
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										qCWarning(logQmlScanner)
 | 
				
			||||||
 | 
										    << "Module path contains invalid characters for a module name: " << end;
 | 
				
			||||||
 | 
										goto skipadd;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								stream << "module qs" << end << '\n';
 | 
				
			||||||
 | 
							skipadd:;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								qCWarning(logQmlScanner) << "Module path" << path << "is outside of the config folder.";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto& singleton: singletons) {
 | 
							for (auto& singleton: singletons) {
 | 
				
			||||||
			stream << "singleton " << singleton.sliced(0, singleton.length() - 4) << " 1.0 " << singleton
 | 
								stream << "singleton " << singleton.sliced(0, singleton.length() - 4) << " 1.0 " << singleton
 | 
				
			||||||
			       << "\n";
 | 
								       << "\n";
 | 
				
			||||||
| 
						 | 
					@ -92,15 +114,39 @@ bool QmlScanner::scanQmlFile(const QString& path) {
 | 
				
			||||||
			qCDebug(logQmlScanner) << "Discovered singleton" << path;
 | 
								qCDebug(logQmlScanner) << "Discovered singleton" << path;
 | 
				
			||||||
			singleton = true;
 | 
								singleton = true;
 | 
				
			||||||
		} else if (line.startsWith("import")) {
 | 
							} else if (line.startsWith("import")) {
 | 
				
			||||||
 | 
								// we dont care about "import qs" as we always load the root folder
 | 
				
			||||||
 | 
								if (auto importCursor = line.indexOf(" qs."); importCursor != -1) {
 | 
				
			||||||
 | 
									importCursor += 4;
 | 
				
			||||||
 | 
									QString path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto startQuot = line.indexOf('"');
 | 
									while (importCursor != line.length()) {
 | 
				
			||||||
			if (startQuot == -1 || line.length() < startQuot + 3) continue;
 | 
										auto c = line.at(importCursor);
 | 
				
			||||||
			auto endQuot = line.indexOf('"', startQuot + 1);
 | 
										if (c == '.') c = '/';
 | 
				
			||||||
			if (endQuot == -1) continue;
 | 
										else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
 | 
				
			||||||
 | 
										         || c == '_')
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											qCWarning(logQmlScanner) << "Import line contains invalid characters: " << line;
 | 
				
			||||||
 | 
											goto next;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto name = line.sliced(startQuot + 1, endQuot - startQuot - 1);
 | 
										path.append(c);
 | 
				
			||||||
			imports.push_back(name);
 | 
										importCursor += 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									imports.append(this->rootPath.filePath(path));
 | 
				
			||||||
 | 
								} else if (auto startQuot = line.indexOf('"');
 | 
				
			||||||
 | 
								           startQuot != -1 && line.length() >= startQuot + 3)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto endQuot = line.indexOf('"', startQuot + 1);
 | 
				
			||||||
 | 
									if (endQuot == -1) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									auto name = line.sliced(startQuot + 1, endQuot - startQuot - 1);
 | 
				
			||||||
 | 
									imports.push_back(name);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} else if (line.contains('{')) break;
 | 
							} else if (line.contains('{')) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						next:;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file.close();
 | 
						file.close();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ public:
 | 
				
			||||||
	QmlScanner() = default;
 | 
						QmlScanner() = default;
 | 
				
			||||||
	QmlScanner(const QDir& rootPath): rootPath(rootPath) {}
 | 
						QmlScanner(const QDir& rootPath): rootPath(rootPath) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// path must be canonical
 | 
				
			||||||
	void scanDir(const QString& path);
 | 
						void scanDir(const QString& path);
 | 
				
			||||||
	// returns if the file has a singleton
 | 
						// returns if the file has a singleton
 | 
				
			||||||
	bool scanQmlFile(const QString& path);
 | 
						bool scanQmlFile(const QString& path);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue