qmldom: pass optional fileType to loadFile

If filetype is given use it to specify the type of the file to
load (otherwise guess it from the file extension).
Can be used to load qmltypes files as "plain" qml files (for
reformatting).
Ths enables the reformatting of .qmltypes (for API comparison)

Change-Id: Ib65647c2a8dc8b37b7e955acb3aec2193d36666d
Pick-to: 6.2
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Fawzi Mohamed 2021-08-09 12:20:35 +02:00 committed by Fawzi Mohamed
parent 06e96fdcde
commit 7331f651c1
5 changed files with 120 additions and 96 deletions

View File

@ -2288,21 +2288,23 @@ DomItem::DomItem(std::shared_ptr<DomUniverse> 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<DomType> fileType)
{
DomItem topEl = top();
if (topEl.internalKind() == DomType::DomEnvironment
|| topEl.internalKind() == DomType::DomUniverse) {
if (auto univ = topEl.ownerAs<DomUniverse>())
univ->loadFile(*this, canonicalFilePath, logicalPath, code, codeDate, callback,
loadOptions);
loadOptions, fileType);
else if (auto env = topEl.ownerAs<DomEnvironment>()) {
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<DomType> 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<DomEnvironment>()) {
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 {

View File

@ -1036,11 +1036,11 @@ public:
DomItem(std::shared_ptr<DomUniverse>);
void loadFile(QString filePath, QString logicalPath,
std::function<void(Path, DomItem &, DomItem &)> callback,
LoadOptions loadOptions);
std::function<void(Path, DomItem &, DomItem &)> callback, LoadOptions loadOptions,
std::optional<DomType> fileType = std::optional<DomType>());
void loadFile(QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate,
std::function<void(Path, DomItem &, DomItem &)> callback,
LoadOptions loadOptions);
std::function<void(Path, DomItem &, DomItem &)> callback, LoadOptions loadOptions,
std::optional<DomType> fileType = std::optional<DomType>());
void loadModuleDependency(QString uri, Version v,
std::function<void(Path, DomItem &, DomItem &)> callback = nullptr,
ErrorHandler = nullptr);

View File

@ -249,56 +249,55 @@ std::shared_ptr<OwningItem> DomUniverse::doCopy(DomItem &) const
}
void DomUniverse::loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback,
LoadOptions loadOptions)
LoadOptions loadOptions, std::optional<DomType> 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<DomType> 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<DomUniverse>(),
callback});
} else if (canonicalFilePath.endsWith(u".qmltypes")) {
m_queue.enqueue(ParsingTask{
QDateTime::currentDateTime(),
loadOptions,
DomType::QmltypesFile,
canonicalFilePath,
logicalPath,
code,
codeDate,
self.ownerAs<DomUniverse>(),
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<DomUniverse>(),
callback});
} else if (QFileInfo(canonicalFilePath).isDir()) {
m_queue.enqueue(ParsingTask { QDateTime::currentDateTime(), loadOptions,
DomType::QmlDirectory, canonicalFilePath, logicalPath, code,
codeDate, self.ownerAs<DomUniverse>(), 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<DomUniverse>(), 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<Import>()) {
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<Reference>()) {
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> 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<DomType> 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<OwningItem> DomEnvironment::doCopy(DomItem &) const
@ -1170,11 +1175,10 @@ std::shared_ptr<OwningItem> 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<DomType> 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<ExternalItemInfoBase> 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<LoadInfo> lInfo = loadInfo(p);

View File

@ -61,6 +61,7 @@
#include <QtCore/QCborMap>
#include <memory>
#include <optional>
QT_BEGIN_NAMESPACE
@ -253,9 +254,11 @@ public:
}
void loadFile(DomItem &self, QString filePath, QString logicalPath, Callback callback,
LoadOptions loadOptions);
LoadOptions loadOptions,
std::optional<DomType> fileType = std::optional<DomType>());
void loadFile(DomItem &self, QString canonicalFilePath, QString logicalPath, QString code,
QDateTime codeDate, Callback callback, LoadOptions loadOptions);
QDateTime codeDate, Callback callback, LoadOptions loadOptions,
std::optional<DomType> fileType = std::optional<DomType>());
void execQueue();
std::shared_ptr<ExternalItemPair<GlobalScope>> 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<DomType> fileType = std::optional<DomType>(),
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<DomType> fileType = std::optional<DomType>(),
ErrorHandler h = nullptr);
void loadModuleDependency(DomItem &self, QString uri, Version v,
Callback loadCallback = nullptr, Callback endCallback = nullptr,
ErrorHandler = nullptr);

View File

@ -41,6 +41,7 @@
#include <QtQmlDom/private/qqmldomfieldfilter_p.h>
#include <cstdio>
#include <optional>
#if QT_CONFIG(commandlineparser)
# include <QtCore/qcommandlineparser.h>
@ -152,6 +153,10 @@ int main(int argc, char *argv[])
}
}
std::optional<DomType> fileType;
if (parser.isSet(reformatOption))
fileType = DomType::QmlFile;
Dependencies dep = Dependencies::None;
for (QString depName : parser.values(dependenciesOption)) {
QMetaEnum metaEnum = QMetaEnum::fromType<Dependencies>();
@ -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<QmlFile> qmlFilePtr = qmlFile.ownerAs<QmlFile>())
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) {