diff --git a/src/qmldom/qqmldomitem.cpp b/src/qmldom/qqmldomitem.cpp index e11761c1e1..49fc3fabda 100644 --- a/src/qmldom/qqmldomitem.cpp +++ b/src/qmldom/qqmldomitem.cpp @@ -2288,21 +2288,23 @@ DomItem::DomItem(std::shared_ptr universePtr): } void DomItem::loadFile(QString canonicalFilePath, QString logicalPath, QString code, - QDateTime codeDate, DomTop::Callback callback, LoadOptions loadOptions) + QDateTime codeDate, DomTop::Callback callback, LoadOptions loadOptions, + std::optional fileType) { DomItem topEl = top(); if (topEl.internalKind() == DomType::DomEnvironment || topEl.internalKind() == DomType::DomUniverse) { if (auto univ = topEl.ownerAs()) univ->loadFile(*this, canonicalFilePath, logicalPath, code, codeDate, callback, - loadOptions); + loadOptions, fileType); else if (auto env = topEl.ownerAs()) { if (env->options() & DomEnvironment::Option::NoDependencies) env->loadFile(topEl, canonicalFilePath, logicalPath, code, codeDate, callback, - DomTop::Callback(), DomTop::Callback(), loadOptions); + DomTop::Callback(), DomTop::Callback(), loadOptions, fileType); else env->loadFile(topEl, canonicalFilePath, logicalPath, code, codeDate, - DomTop::Callback(), DomTop::Callback(), callback, loadOptions); + DomTop::Callback(), DomTop::Callback(), callback, loadOptions, + fileType); } else Q_ASSERT(false && "expected either DomUniverse or DomEnvironment cast to succeed"); } else { @@ -2312,7 +2314,7 @@ void DomItem::loadFile(QString canonicalFilePath, QString logicalPath, QString c } void DomItem::loadFile(QString filePath, QString logicalPath, DomTop::Callback callback, - LoadOptions loadOptions) + LoadOptions loadOptions, std::optional fileType) { DomItem topEl = top(); if (topEl.internalKind() == DomType::DomEnvironment @@ -2322,10 +2324,10 @@ void DomItem::loadFile(QString filePath, QString logicalPath, DomTop::Callback c else if (auto env = topEl.ownerAs()) { if (env->options() & DomEnvironment::Option::NoDependencies) env->loadFile(topEl, filePath, logicalPath, callback, DomTop::Callback(), - DomTop::Callback(), loadOptions); + DomTop::Callback(), loadOptions, fileType); else env->loadFile(topEl, filePath, logicalPath, DomTop::Callback(), DomTop::Callback(), - callback, loadOptions); + callback, loadOptions, fileType); } else Q_ASSERT(false && "expected either DomUniverse or DomEnvironment cast to succeed"); } else { diff --git a/src/qmldom/qqmldomitem_p.h b/src/qmldom/qqmldomitem_p.h index 52a19b71c9..c3720d74ea 100644 --- a/src/qmldom/qqmldomitem_p.h +++ b/src/qmldom/qqmldomitem_p.h @@ -1036,11 +1036,11 @@ public: DomItem(std::shared_ptr); void loadFile(QString filePath, QString logicalPath, - std::function callback, - LoadOptions loadOptions); + std::function callback, LoadOptions loadOptions, + std::optional fileType = std::optional()); void loadFile(QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, - std::function callback, - LoadOptions loadOptions); + std::function callback, LoadOptions loadOptions, + std::optional fileType = std::optional()); void loadModuleDependency(QString uri, Version v, std::function callback = nullptr, ErrorHandler = nullptr); diff --git a/src/qmldom/qqmldomtop.cpp b/src/qmldom/qqmldomtop.cpp index e42506d632..5df34eedad 100644 --- a/src/qmldom/qqmldomtop.cpp +++ b/src/qmldom/qqmldomtop.cpp @@ -249,56 +249,55 @@ std::shared_ptr DomUniverse::doCopy(DomItem &) const } void DomUniverse::loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback, - LoadOptions loadOptions) + LoadOptions loadOptions, std::optional fileType) { - loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), callback, loadOptions); + loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), callback, + loadOptions, fileType); +} + +static DomType fileTypeForPath(DomItem &self, QString canonicalFilePath) +{ + if (canonicalFilePath.endsWith(u".qml", Qt::CaseInsensitive) + || canonicalFilePath.endsWith(u".qmlannotation", Qt::CaseInsensitive)) { + return DomType::QmlFile; + } else if (canonicalFilePath.endsWith(u".qmltypes")) { + return DomType::QmltypesFile; + } else if (QStringView(u"qmldir").compare(QFileInfo(canonicalFilePath).fileName(), + Qt::CaseInsensitive) + == 0) { + return DomType::QmltypesFile; + } else if (QFileInfo(canonicalFilePath).isDir()) { + return DomType::QmlDirectory; + } else { + self.addError(DomUniverse::myErrors() + .error(QCoreApplication::translate("Dom::filteTypeForPath", + "Could not detect type of file %1") + .arg(canonicalFilePath)) + .handle()); + } + return DomType::Empty; } void DomUniverse::loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, Callback callback, - LoadOptions loadOptions) + LoadOptions loadOptions, std::optional fileType) { - if (canonicalFilePath.endsWith(u".qml", Qt::CaseInsensitive) || - canonicalFilePath.endsWith(u".qmlannotation", Qt::CaseInsensitive) || - canonicalFilePath.endsWith(u".ui", Qt::CaseInsensitive)) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmlFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs(), - callback}); - } else if (canonicalFilePath.endsWith(u".qmltypes")) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmltypesFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs(), - callback}); - } else if (QStringView(u"qmldir").compare(QFileInfo(canonicalFilePath).fileName(), Qt::CaseInsensitive) == 0) { - m_queue.enqueue(ParsingTask{ - QDateTime::currentDateTime(), - loadOptions, - DomType::QmldirFile, - canonicalFilePath, - logicalPath, - code, - codeDate, - self.ownerAs(), - callback}); - } else if (QFileInfo(canonicalFilePath).isDir()) { - m_queue.enqueue(ParsingTask { QDateTime::currentDateTime(), loadOptions, - DomType::QmlDirectory, canonicalFilePath, logicalPath, code, - codeDate, self.ownerAs(), callback }); - } else { - self.addError(myErrors().error(tr("Ignoring request to load file of unknown type %1, calling callback immediately").arg(canonicalFilePath)).handle()); + DomType fType = (bool(fileType) ? (*fileType) : fileTypeForPath(self, canonicalFilePath)); + switch (fType) { + case DomType::QmlFile: + case DomType::QmltypesFile: + case DomType::QmldirFile: + case DomType::QmlDirectory: + m_queue.enqueue(ParsingTask { QDateTime::currentDateTime(), loadOptions, fType, + canonicalFilePath, logicalPath, code, codeDate, + self.ownerAs(), callback }); + break; + default: + self.addError(myErrors() + .error(tr("Ignoring request to load file %1 of unexpected type %2, " + "calling callback immediately") + .arg(canonicalFilePath, domTypeToString(fType))) + .handle()); Q_ASSERT(false && "loading non supported file type"); callback(Path(), DomItem::empty, DomItem::empty); return; @@ -629,7 +628,8 @@ void LoadInfo::advanceLoad(DomItem &self) [this, self, dep](Path, DomItem &, DomItem &) mutable { finishedLoadingDep(self, dep); }, - nullptr, nullptr, LoadOption::DefaultLoad, self.errorHandler()); + nullptr, nullptr, LoadOption::DefaultLoad, dep.fileType, + self.errorHandler()); else Q_ASSERT(false && "missing environment"); } else { @@ -749,12 +749,13 @@ void LoadInfo::doAddDependencies(DomItem &self) DomItem import = currentImports.index(i); if (const Import *importPtr = import.as()) { if (!importPtr->filePath().isEmpty()) { - addDependency( - self, - Dependency { QString(), importPtr->version, importPtr->filePath() }); + addDependency(self, + Dependency { QString(), importPtr->version, importPtr->filePath(), + DomType::Empty }); } else { addDependency(self, - Dependency { importPtr->uri, importPtr->version, QString() }); + Dependency { importPtr->uri, importPtr->version, QString(), + DomType::ModuleIndex }); } } } @@ -766,7 +767,8 @@ void LoadInfo::doAddDependencies(DomItem &self) Path canonicalPath = ref->referredObjectPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) addDependency(self, - Dependency { QString(), Version(), canonicalPath.headName() }); + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmltypesFile }); } } DomItem currentQmlFiles = el.field(Fields::currentItem).field(Fields::qmlFiles); @@ -775,9 +777,9 @@ void LoadInfo::doAddDependencies(DomItem &self) if (const Reference *ref = el.as()) { Path canonicalPath = ref->referredObjectPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) - addDependency( - self, - Dependency { QString(), Version(), canonicalPath.headName() }); + addDependency(self, + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmlFile }); } return true; }); @@ -786,7 +788,9 @@ void LoadInfo::doAddDependencies(DomItem &self) for (Path qmldirPath : elPtr->qmldirsToLoad(el)) { Path canonicalPath = qmldirPath[2]; if (canonicalPath && !canonicalPath.headName().isEmpty()) - addDependency(self, Dependency { QString(), Version(), canonicalPath.headName() }); + addDependency(self, + Dependency { QString(), Version(), canonicalPath.headName(), + DomType::QmldirFile }); } } else if (!el) { self.addError(DomEnvironment::myErrors().error( @@ -1150,10 +1154,11 @@ std::shared_ptr DomEnvironment::makeCopy(DomItem &self) const void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPath, DomTop::Callback loadCallback, DomTop::Callback directDepsCallback, - DomTop::Callback endCallback, LoadOptions loadOptions, ErrorHandler h) + DomTop::Callback endCallback, LoadOptions loadOptions, + std::optional fileType, ErrorHandler h) { loadFile(self, filePath, logicalPath, QString(), QDateTime::fromMSecsSinceEpoch(0), - loadCallback, directDepsCallback, endCallback, loadOptions, h); + loadCallback, directDepsCallback, endCallback, loadOptions, fileType, h); } std::shared_ptr DomEnvironment::doCopy(DomItem &) const @@ -1170,11 +1175,10 @@ std::shared_ptr DomEnvironment::doCopy(DomItem &) const void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPath, QString code, QDateTime codeDate, Callback loadCallback, Callback directDepsCallback, Callback endCallback, - LoadOptions loadOptions, ErrorHandler h) + LoadOptions loadOptions, std::optional fileType, + ErrorHandler h) { QFileInfo fileInfo(filePath); - bool isDir = fileInfo.isDir(); - QString ext = fileInfo.suffix(); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { if (code.isNull()) { @@ -1193,7 +1197,9 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa } } shared_ptr oldValue, newValue; - if (isDir) { + DomType fType = (bool(fileType) ? (*fileType) : fileTypeForPath(self, canonicalFilePath)); + switch (fType) { + case DomType::QmlDirectory: { { QMutexLocker l(mutex()); auto it = m_qmlDirectoryWithPath.find(canonicalFilePath); @@ -1220,10 +1226,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmlDirectory(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (ext == u"qml" || ext == u"ui" || ext == u"qmlannotation") { + } break; + case DomType::QmlFile: { { QMutexLocker l(mutex()); auto it = m_qmlFileWithPath.find(canonicalFilePath); @@ -1249,10 +1256,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmlFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (ext == u"qmltypes") { + } break; + case DomType::QmltypesFile: { { QMutexLocker l(mutex()); auto it = m_qmltypesFileWithPath.find(canonicalFilePath); @@ -1279,10 +1287,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmltypesFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else if (fileInfo.fileName() == u"qmldir") { + } break; + case DomType::QmldirFile: { { QMutexLocker l(mutex()); auto it = m_qmldirFileWithPath.find(canonicalFilePath); @@ -1308,10 +1317,11 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa self.universe().loadFile( canonicalFilePath, logicalPath, code, codeDate, callbackForQmldirFile(self, loadCallback, directDepsCallback, endCallback), - loadOptions); + loadOptions, fType); return; } - } else { + } break; + default: { myErrors().error(tr("Unexpected file to load: '%1'").arg(filePath)).handle(h); if (loadCallback) loadCallback(self.canonicalPath(), DomItem::empty, DomItem::empty); @@ -1320,6 +1330,7 @@ void DomEnvironment::loadFile(DomItem &self, QString filePath, QString logicalPa if (endCallback) endCallback(self.canonicalPath(), DomItem::empty, DomItem::empty); return; + } break; } Path p = self.copy(newValue).canonicalPath(); std::shared_ptr lInfo = loadInfo(p); diff --git a/src/qmldom/qqmldomtop_p.h b/src/qmldom/qqmldomtop_p.h index 4c905991af..eeb0038d09 100644 --- a/src/qmldom/qqmldomtop_p.h +++ b/src/qmldom/qqmldomtop_p.h @@ -61,6 +61,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -253,9 +254,11 @@ public: } void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback, - LoadOptions loadOptions); + LoadOptions loadOptions, + std::optional fileType = std::optional()); void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, - QDateTime codeDate, Callback callback, LoadOptions loadOptions); + QDateTime codeDate, Callback callback, LoadOptions loadOptions, + std::optional fileType = std::optional()); void execQueue(); std::shared_ptr> globalScopeWithName(QString name) const @@ -517,6 +520,7 @@ public: QString uri; // either dotted uri or file:, http: https: uri Version version; QString filePath; // for file deps + DomType fileType; }; class QMLDOM_EXPORT LoadInfo final : public OwningItem @@ -683,10 +687,13 @@ public: void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback loadCallback, Callback directDepsCallback, Callback endCallback, LoadOptions loadOptions, + std::optional fileType = std::optional(), ErrorHandler h = nullptr); void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate, Callback loadCallback, Callback directDepsCallback, - Callback endCallback, LoadOptions loadOptions, ErrorHandler h = nullptr); + Callback endCallback, LoadOptions loadOptions, + std::optional fileType = std::optional(), + ErrorHandler h = nullptr); void loadModuleDependency(DomItem &self, QString uri, Version v, Callback loadCallback = nullptr, Callback endCallback = nullptr, ErrorHandler = nullptr); diff --git a/tools/qmldom/qmldomtool.cpp b/tools/qmldom/qmldomtool.cpp index 8efa652082..c70b77b520 100644 --- a/tools/qmldom/qmldomtool.cpp +++ b/tools/qmldom/qmldomtool.cpp @@ -41,6 +41,7 @@ #include #include +#include #if QT_CONFIG(commandlineparser) # include @@ -152,6 +153,10 @@ int main(int argc, char *argv[]) } } + std::optional fileType; + if (parser.isSet(reformatOption)) + fileType = DomType::QmlFile; + Dependencies dep = Dependencies::None; for (QString depName : parser.values(dependenciesOption)) { QMetaEnum metaEnum = QMetaEnum::fromType(); @@ -230,15 +235,22 @@ int main(int argc, char *argv[]) if (dep != Dependencies::None) env.loadBuiltins(); foreach (QString s, positionalArguments) { - env.loadFile(s, QString(), nullptr, LoadOption::DefaultLoad); + env.loadFile(s, QString(), nullptr, LoadOption::DefaultLoad, fileType); } envPtr->loadPendingDependencies(env); + bool hadFailures = false; + const qsizetype largestFileSizeToCheck = 32000; if (parser.isSet(reformatOption)) { for (auto s : positionalArguments) { - DomItem qmlFile = env.path(Paths::qmldirFilePath(s)); + DomItem qmlFile = env.path(Paths::qmlFilePath(QFileInfo(s).canonicalFilePath())); if (qmlFile) { qDebug() << "reformatting" << s; FileWriter fw; + LineWriterOptions lwOptions; + WriteOutChecks checks = WriteOutCheck::Default; + if (std::shared_ptr qmlFilePtr = qmlFile.ownerAs()) + if (qmlFilePtr->code().size() > largestFileSizeToCheck) + checks = WriteOutCheck::None; QString target = s; QString rDir = parser.value(reformatDirOption); if (!rDir.isEmpty()) { @@ -246,16 +258,8 @@ int main(int argc, char *argv[]) QDir d(rDir); target = d.filePath(f.fileName()); } - switch (fw.write( - target, - [&qmlFile, target](QTextStream &ts) { - LineWriter lw([&ts](QStringView s) { ts << s; }, target); - OutWriter ow(lw); - qmlFile.writeOut(ow); - ow.eof(); - return true; - }, - nBackups)) { + MutableDomItem res = qmlFile.writeOut(target, nBackups, lwOptions, &fw, checks); + switch (fw.status) { case FileWriter::Status::ShouldWrite: case FileWriter::Status::SkippedDueToFailure: qWarning() << "failure reformatting " << s; @@ -266,10 +270,10 @@ int main(int argc, char *argv[]) case FileWriter::Status::SkippedEqual: qDebug() << "no change"; } + hadFailures = hadFailures || !bool(res); } } - } - if (parser.isSet(dumpOption) || !parser.isSet(reformatOption)) { + } else if (parser.isSet(dumpOption) || !parser.isSet(reformatOption)) { qDebug() << "will dump\n"; QTextStream ts(stdout); auto sink = [&ts](QStringView v) {