core: add Internal pragma

This commit is contained in:
outfoxxed 2025-07-16 20:13:59 -07:00
parent 78e3874ac6
commit 201c559dcd
Signed by untrusted user: outfoxxed
GPG key ID: 4C88A185FB89301E
3 changed files with 47 additions and 32 deletions

View file

@ -58,7 +58,7 @@ void RootWrapper::reloadGraph(bool hard) {
auto rootFile = QFileInfo(this->rootPath); auto rootFile = QFileInfo(this->rootPath);
auto rootPath = rootFile.dir(); auto rootPath = rootFile.dir();
auto scanner = QmlScanner(rootPath); auto scanner = QmlScanner(rootPath);
scanner.scanQmlFile(this->rootPath); scanner.scanQmlRoot(this->rootPath);
qs::core::QmlToolingSupport::updateTooling(rootPath, scanner); qs::core::QmlToolingSupport::updateTooling(rootPath, scanner);
this->configDirWatcher.addPath(rootPath.path()); this->configDirWatcher.addPath(rootPath.path());

View file

@ -26,30 +26,41 @@ void QmlScanner::scanDir(const QString& path) {
qCDebug(logQmlScanner) << "Scanning directory" << path; qCDebug(logQmlScanner) << "Scanning directory" << path;
auto dir = QDir(path); auto dir = QDir(path);
struct Entry {
QString name;
bool singleton = false;
bool internal = false;
};
bool seenQmldir = false; bool seenQmldir = false;
auto singletons = QVector<QString>(); auto entries = QVector<Entry>();
auto entries = QVector<QString>();
for (auto& entry: dir.entryList(QDir::Files | QDir::NoDotAndDotDot)) { for (auto& name: dir.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
if (entry == "qmldir") { if (name == "qmldir") {
qCDebug(logQmlScanner qCDebug(logQmlScanner
) << "Found qmldir file, qmldir synthesization will be disabled for directory" ) << "Found qmldir file, qmldir synthesization will be disabled for directory"
<< path; << path;
seenQmldir = true; seenQmldir = true;
} else if (entry.at(0).isUpper() && entry.endsWith(".qml")) { } else if (name.at(0).isUpper() && name.endsWith(".qml")) {
if (this->scanQmlFile(dir.filePath(entry))) { auto& entry = entries.emplaceBack();
singletons.push_back(entry);
if (this->scanQmlFile(dir.filePath(name), entry.singleton, entry.internal)) {
entry.name = name;
} else { } else {
entries.push_back(entry); entries.pop_back();
}
} else if (name.at(0).isUpper() && name.endsWith(".qml.json")) {
if (this->scanQmlJson(dir.filePath(name))) {
entries.push_back({
.name = name.first(name.length() - 5),
.singleton = true,
});
} }
} else if (entry.at(0).isUpper() && entry.endsWith(".qml.json")) {
this->scanQmlJson(dir.filePath(entry));
singletons.push_back(entry.first(entry.length() - 5));
} }
} }
if (!seenQmldir) { if (!seenQmldir) {
qCDebug(logQmlScanner) << "Synthesizing qmldir for directory" << path << "singletons" qCDebug(logQmlScanner) << "Synthesizing qmldir for directory" << path;
<< singletons;
QString qmldir; QString qmldir;
auto stream = QTextStream(&qmldir); auto stream = QTextStream(&qmldir);
@ -77,13 +88,10 @@ void QmlScanner::scanDir(const QString& path) {
qCWarning(logQmlScanner) << "Module path" << path << "is outside of the config folder."; qCWarning(logQmlScanner) << "Module path" << path << "is outside of the config folder.";
} }
for (auto& singleton: singletons) { for (const auto& entry: entries) {
stream << "singleton " << singleton.sliced(0, singleton.length() - 4) << " 1.0 " << singleton if (entry.internal) stream << "internal ";
<< "\n"; if (entry.singleton) stream << "singleton ";
} stream << entry.name.sliced(0, entry.name.length() - 4) << " 1.0 " << entry.name << '\n';
for (auto& entry: entries) {
stream << entry.sliced(0, entry.length() - 4) << " 1.0 " << entry << "\n";
} }
qCDebug(logQmlScanner) << "Synthesized qmldir for" << path << qPrintable("\n" + qmldir); qCDebug(logQmlScanner) << "Synthesized qmldir for" << path << qPrintable("\n" + qmldir);
@ -91,7 +99,7 @@ void QmlScanner::scanDir(const QString& path) {
} }
} }
bool QmlScanner::scanQmlFile(const QString& path) { bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& internal) {
if (this->scannedFiles.contains(path)) return false; if (this->scannedFiles.contains(path)) return false;
this->scannedFiles.push_back(path); this->scannedFiles.push_back(path);
@ -106,13 +114,12 @@ bool QmlScanner::scanQmlFile(const QString& path) {
auto stream = QTextStream(&file); auto stream = QTextStream(&file);
auto imports = QVector<QString>(); auto imports = QVector<QString>();
bool singleton = false;
while (!stream.atEnd()) { while (!stream.atEnd()) {
auto line = stream.readLine().trimmed(); auto line = stream.readLine().trimmed();
if (!singleton && line == "pragma Singleton") { if (!singleton && line == "pragma Singleton") {
qCDebug(logQmlScanner) << "Discovered singleton" << path;
singleton = true; singleton = true;
} else if (!internal && line == "//@ pragma Internal") {
internal = true;
} else if (line.startsWith("import")) { } else if (line.startsWith("import")) {
// we dont care about "import qs" as we always load the root folder // we dont care about "import qs" as we always load the root folder
if (auto importCursor = line.indexOf(" qs."); importCursor != -1) { if (auto importCursor = line.indexOf(" qs."); importCursor != -1) {
@ -188,16 +195,22 @@ bool QmlScanner::scanQmlFile(const QString& path) {
else this->scanDir(cpath); else this->scanDir(cpath);
} }
return singleton; return true;
} }
void QmlScanner::scanQmlJson(const QString& path) { void QmlScanner::scanQmlRoot(const QString& path) {
bool singleton = false;
bool internal = false;
this->scanQmlFile(path, singleton, internal);
}
bool QmlScanner::scanQmlJson(const QString& path) {
qCDebug(logQmlScanner) << "Scanning qml.json file" << path; qCDebug(logQmlScanner) << "Scanning qml.json file" << path;
auto file = QFile(path); auto file = QFile(path);
if (!file.open(QFile::ReadOnly | QFile::Text)) { if (!file.open(QFile::ReadOnly | QFile::Text)) {
qCWarning(logQmlScanner) << "Failed to open file" << path; qCWarning(logQmlScanner) << "Failed to open file" << path;
return; return false;
} }
auto data = file.readAll(); auto data = file.readAll();
@ -209,7 +222,7 @@ void QmlScanner::scanQmlJson(const QString& path) {
if (error.error != QJsonParseError::NoError) { if (error.error != QJsonParseError::NoError) {
qCCritical(logQmlScanner).nospace() qCCritical(logQmlScanner).nospace()
<< "Failed to parse qml.json file at " << path << ": " << error.errorString(); << "Failed to parse qml.json file at " << path << ": " << error.errorString();
return; return false;
} }
const QString body = const QString body =
@ -219,6 +232,7 @@ void QmlScanner::scanQmlJson(const QString& path) {
this->fileIntercepts.insert(path.first(path.length() - 5), body); this->fileIntercepts.insert(path.first(path.length() - 5), body);
this->scannedFiles.push_back(path); this->scannedFiles.push_back(path);
return true;
} }
QPair<QString, QString> QmlScanner::jsonToQml(const QJsonValue& value, int indent) { QPair<QString, QString> QmlScanner::jsonToQml(const QJsonValue& value, int indent) {

View file

@ -18,8 +18,8 @@ public:
// path must be canonical // path must be canonical
void scanDir(const QString& path); void scanDir(const QString& path);
// returns if the file has a singleton
bool scanQmlFile(const QString& path); void scanQmlRoot(const QString& path);
QVector<QString> scannedDirs; QVector<QString> scannedDirs;
QVector<QString> scannedFiles; QVector<QString> scannedFiles;
@ -28,6 +28,7 @@ public:
private: private:
QDir rootPath; QDir rootPath;
void scanQmlJson(const QString& path); bool scanQmlFile(const QString& path, bool& singleton, bool& internal);
bool scanQmlJson(const QString& path);
[[nodiscard]] static QPair<QString, QString> jsonToQml(const QJsonValue& value, int indent = 0); [[nodiscard]] static QPair<QString, QString> jsonToQml(const QJsonValue& value, int indent = 0);
}; };