QmlDesigner: Adapt to QmlDom changes

Task-number: QDS-6799
Change-Id: Ic37d8549c9a6fd8bca770b07b0dcb0f84892841b
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2022-04-27 17:10:17 +02:00
parent 171384c0db
commit 739b32e54a
8 changed files with 194 additions and 93 deletions

View File

@@ -97,7 +97,7 @@ private:
const QList<QmlDirParser::Import> &qmldirDependencies, const QList<QmlDirParser::Import> &qmldirDependencies,
const QList<QmlDirParser::Import> &qmldirImports, const QList<QmlDirParser::Import> &qmldirImports,
SourceId qmldirSourceId, SourceId qmldirSourceId,
SourceContextId directoryId, Utils::SmallStringView directoryPath,
ModuleId moduleId, ModuleId moduleId,
Storage::SynchronizationPackage &package, Storage::SynchronizationPackage &package,
SourceIds &notUpdatedFileStatusSourceIds, SourceIds &notUpdatedFileStatusSourceIds,
@@ -115,11 +115,13 @@ private:
SourceId qmldirSourceId, SourceId qmldirSourceId,
SourceContextId directoryId, SourceContextId directoryId,
ModuleId moduleId, ModuleId moduleId,
ModuleId pathModuleId,
Storage::SynchronizationPackage &package, Storage::SynchronizationPackage &package,
SourceIds &notUpdatedFileStatusSourceIds); SourceIds &notUpdatedFileStatusSourceIds);
void parseQmlComponents(const Storage::ProjectDatas &projectDatas, void parseQmlComponents(const Storage::ProjectDatas &projectDatas,
Storage::SynchronizationPackage &package, Storage::SynchronizationPackage &package,
SourceIds &notUpdatedFileStatusSourceIds); SourceIds &notUpdatedFileStatusSourceIds,
Utils::SmallStringView directoryPath);
void parseQmlComponent(Utils::SmallStringView fileName, void parseQmlComponent(Utils::SmallStringView fileName,
Utils::SmallStringView directory, Utils::SmallStringView directory,
Storage::ExportedTypes exportedTypes, Storage::ExportedTypes exportedTypes,
@@ -129,6 +131,7 @@ private:
SourceIds &notUpdatedFileStatusSourceIds); SourceIds &notUpdatedFileStatusSourceIds);
void parseQmlComponent(Utils::SmallStringView fileName, void parseQmlComponent(Utils::SmallStringView fileName,
Utils::SmallStringView filePath, Utils::SmallStringView filePath,
Utils::SmallStringView directoryPath,
SourceId sourceId, SourceId sourceId,
Storage::SynchronizationPackage &package, Storage::SynchronizationPackage &package,
SourceIds &notUpdatedFileStatusSourceIds); SourceIds &notUpdatedFileStatusSourceIds);

View File

@@ -1,3 +1,4 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
@@ -54,16 +55,20 @@ Storage::Version convertVersion(QmlDom::Version version)
convertVersionNumber(version.minorVersion)}; convertVersionNumber(version.minorVersion)};
} }
Utils::PathString convertUri(const QString &uri) Utils::PathString createNormalizedPath(Utils::SmallStringView directoryPath,
const QString &relativePath)
{ {
QStringView localPath{uri.begin() + 7, uri.end()}; std::filesystem::path modulePath{std::string_view{directoryPath},
std::filesystem::path::format::generic_format};
std::filesystem::path path{ modulePath /= relativePath.toStdString();
std::u16string_view{localPath.utf16(), static_cast<std::size_t>(localPath.size())}};
auto x = std::filesystem::weakly_canonical(path); Utils::PathString normalizedPath = modulePath.lexically_normal().generic_string();
return Utils::PathString{x.generic_string()}; if (normalizedPath[normalizedPath.size() - 1] == '/')
normalizedPath.resize(normalizedPath.size() - 1);
return normalizedPath;
} }
Storage::Import createImport(const QmlDom::Import &qmlImport, Storage::Import createImport(const QmlDom::Import &qmlImport,
@@ -71,21 +76,26 @@ Storage::Import createImport(const QmlDom::Import &qmlImport,
Utils::SmallStringView directoryPath, Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage) QmlDocumentParser::ProjectStorage &storage)
{ {
if (qmlImport.uri == u"file://.") { using QmlUriKind = QQmlJS::Dom::QmlUri::Kind;
auto moduleId = storage.moduleId(directoryPath);
auto &&uri = qmlImport.uri;
if (uri.kind() == QmlUriKind::RelativePath) {
auto path = createNormalizedPath(directoryPath, uri.localPath());
auto moduleId = storage.moduleId(createNormalizedPath(directoryPath, uri.localPath()));
return Storage::Import(moduleId, Storage::Version{}, sourceId); return Storage::Import(moduleId, Storage::Version{}, sourceId);
} }
if (qmlImport.uri.startsWith(u"file://")) { if (uri.kind() == QmlUriKind::ModuleUri) {
auto moduleId = storage.moduleId(convertUri(qmlImport.uri)); auto moduleId = storage.moduleId(Utils::PathString{uri.moduleUri()});
return Storage::Import(moduleId, Storage::Version{}, sourceId); return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
} }
auto moduleId = storage.moduleId(Utils::SmallString{qmlImport.uri}); auto moduleId = storage.moduleId(Utils::PathString{uri.toString()});
return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId); return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
} }
QualifiedImports filterQualifiedImports(const QList<QmlDom::Import> &qmlImports, QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
SourceId sourceId, SourceId sourceId,
Utils::SmallStringView directoryPath, Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage) QmlDocumentParser::ProjectStorage &storage)
@@ -93,7 +103,7 @@ QualifiedImports filterQualifiedImports(const QList<QmlDom::Import> &qmlImports,
QualifiedImports qualifiedImports; QualifiedImports qualifiedImports;
for (const QmlDom::Import &qmlImport : qmlImports) { for (const QmlDom::Import &qmlImport : qmlImports) {
if (!qmlImport.importId.isEmpty()) if (!qmlImport.importId.isEmpty() && !qmlImport.implicit)
qualifiedImports.try_emplace(qmlImport.importId, qualifiedImports.try_emplace(qmlImport.importId,
createImport(qmlImport, sourceId, directoryPath, storage)); createImport(qmlImport, sourceId, directoryPath, storage));
} }
@@ -107,11 +117,24 @@ void addImports(Storage::Imports &imports,
Utils::SmallStringView directoryPath, Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage) QmlDocumentParser::ProjectStorage &storage)
{ {
for (const QmlDom::Import &qmlImport : qmlImports) int importCount = 0;
for (const QmlDom::Import &qmlImport : qmlImports) {
if (!qmlImport.implicit) {
imports.push_back(createImport(qmlImport, sourceId, directoryPath, storage)); imports.push_back(createImport(qmlImport, sourceId, directoryPath, storage));
++importCount;
}
}
auto localDirectoryModuleId = storage.moduleId(directoryPath);
imports.emplace_back(localDirectoryModuleId, Storage::Version{}, sourceId);
++importCount;
auto qmlModuleId = storage.moduleId("QML");
imports.emplace_back(qmlModuleId, Storage::Version{}, sourceId);
++importCount;
auto end = imports.end(); auto end = imports.end();
auto begin = std::prev(end, qmlImports.size()); auto begin = std::prev(end, importCount);
std::sort(begin, end); std::sort(begin, end);
imports.erase(std::unique(begin, end), end); imports.erase(std::unique(begin, end), end);
@@ -196,14 +219,17 @@ void addEnumeraton(Storage::Type &type, const QmlDom::Component &component)
Storage::Type QmlDocumentParser::parse(const QString &sourceContent, Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
Storage::Imports &imports, Storage::Imports &imports,
SourceId sourceId) SourceId sourceId,
Utils::SmallStringView directoryPath)
{ {
Storage::Type type; Storage::Type type;
QmlDom::DomItem environment = QmlDom::DomEnvironment::create( using Option = QmlDom::DomEnvironment::Option;
{},
QmlDom::DomEnvironment::Option::SingleThreaded QmlDom::DomItem environment = QmlDom::DomEnvironment::create({},
| QmlDom::DomEnvironment::Option::NoDependencies); Option::SingleThreaded
| Option::NoDependencies
| Option::WeakLoad);
QmlDom::DomItem items; QmlDom::DomItem items;
@@ -238,9 +264,11 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
const QmlDom::QmlObject &qmlObject = objects.front(); const QmlDom::QmlObject &qmlObject = objects.front();
const auto qmlImports = qmlFile->imports(); const auto qmlImports = qmlFile->imports();
auto directoryPath{m_pathCache.sourceContextPath(m_pathCache.sourceContextId(sourceId))};
const auto qualifiedImports = filterQualifiedImports(qmlImports, sourceId, directoryPath, m_storage); const auto qualifiedImports = createQualifiedImports(qmlImports,
sourceId,
directoryPath,
m_storage);
type.prototype = createImportedTypeName(qmlObject.name(), qualifiedImports); type.prototype = createImportedTypeName(qmlObject.name(), qualifiedImports);

View File

@@ -53,7 +53,8 @@ public:
Storage::Type parse(const QString &sourceContent, Storage::Type parse(const QString &sourceContent,
Storage::Imports &imports, Storage::Imports &imports,
SourceId sourceId) override; SourceId sourceId,
Utils::SmallStringView directoryPath) override;
private: private:
ProjectStorage &m_storage; ProjectStorage &m_storage;

View File

@@ -34,7 +34,11 @@ namespace QmlDesigner {
class QmlDocumentParserInterface class QmlDocumentParserInterface
{ {
public: public:
virtual Storage::Type parse(const QString &sourceContent, Storage::Imports &imports, SourceId sourceId) = 0; virtual Storage::Type parse(const QString &sourceContent,
Storage::Imports &imports,
SourceId sourceId,
Utils::SmallStringView directoryPath)
= 0;
protected: protected:
~QmlDocumentParserInterface() = default; ~QmlDocumentParserInterface() = default;

View File

@@ -47,7 +47,7 @@ namespace {
using ComponentWithoutNamespaces = QMap<QString, QString>; using ComponentWithoutNamespaces = QMap<QString, QString>;
ComponentWithoutNamespaces createComponentNameWithoutNamespaces( ComponentWithoutNamespaces createComponentNameWithoutNamespaces(
const QHash<QString, QQmlJSScope::Ptr> &objects) const QHash<QString, QQmlJSExportedScope> &objects)
{ {
ComponentWithoutNamespaces componentWithoutNamespaces; ComponentWithoutNamespaces componentWithoutNamespaces;
@@ -409,15 +409,17 @@ EnumerationTypes addEnumerationTypes(Storage::Types &types,
void addType(Storage::Types &types, void addType(Storage::Types &types,
SourceId sourceId, SourceId sourceId,
ModuleId cppModuleId, ModuleId cppModuleId,
const QQmlJSScope &component, const QQmlJSExportedScope &exportScope,
QmlTypesParser::ProjectStorage &storage, QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespace) const ComponentWithoutNamespaces &componentNameWithoutNamespace)
{ {
const auto &component = *exportScope.scope;
auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals( auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals(
component.ownMethods(), componentNameWithoutNamespace); component.ownMethods(), componentNameWithoutNamespace);
TypeNameString typeName{component.internalName()}; TypeNameString typeName{component.internalName()};
auto enumerations = component.ownEnumerations(); auto enumerations = component.ownEnumerations();
auto exports = component.exports(); auto exports = exportScope.exports;
auto enumerationTypes = addEnumerationTypes(types, typeName, sourceId, cppModuleId, enumerations); auto enumerationTypes = addEnumerationTypes(types, typeName, sourceId, cppModuleId, enumerations);
types.emplace_back(Utils::SmallStringView{typeName}, types.emplace_back(Utils::SmallStringView{typeName},
@@ -435,7 +437,7 @@ void addType(Storage::Types &types,
void addTypes(Storage::Types &types, void addTypes(Storage::Types &types,
const Storage::ProjectData &projectData, const Storage::ProjectData &projectData,
const QHash<QString, QQmlJSScope::Ptr> &objects, const QHash<QString, QQmlJSExportedScope> &objects,
QmlTypesParser::ProjectStorage &storage, QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespaces) const ComponentWithoutNamespaces &componentNameWithoutNamespaces)
{ {
@@ -445,7 +447,7 @@ void addTypes(Storage::Types &types,
addType(types, addType(types,
projectData.sourceId, projectData.sourceId,
projectData.moduleId, projectData.moduleId,
*object.get(), object,
storage, storage,
componentNameWithoutNamespaces); componentNameWithoutNamespaces);
} }
@@ -458,7 +460,7 @@ void QmlTypesParser::parse(const QString &sourceContent,
const Storage::ProjectData &projectData) const Storage::ProjectData &projectData)
{ {
QQmlJSTypeDescriptionReader reader({}, sourceContent); QQmlJSTypeDescriptionReader reader({}, sourceContent);
QHash<QString, QQmlJSScope::Ptr> components; QHash<QString, QQmlJSExportedScope> components;
QStringList dependencies; QStringList dependencies;
bool isValid = reader(&components, &dependencies); bool isValid = reader(&components, &dependencies);
if (!isValid) if (!isValid)

View File

@@ -183,7 +183,7 @@ public:
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
.WillByDefault(Return(qmlDocument1)); .WillByDefault(Return(qmlDocument1));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First2.qml"))))
.WillByDefault(Return(qmlDocument2)); .WillByDefault(Return(qmlDocument2));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
.WillByDefault(Return(qmlDocument3)); .WillByDefault(Return(qmlDocument3));
@@ -192,18 +192,18 @@ public:
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/types/example2.qmltypes")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/types/example2.qmltypes"))))
.WillByDefault(Return(qmltypes2)); .WillByDefault(Return(qmltypes2));
ON_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _)) ON_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _))
.WillByDefault([&](auto, auto &imports, auto) { .WillByDefault([&](auto, auto &imports, auto, auto) {
imports.push_back(import1); imports.push_back(import1);
return firstType; return firstType;
}); });
ON_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _)) ON_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _))
.WillByDefault([&](auto, auto &imports, auto) { .WillByDefault([&](auto, auto &imports, auto, auto) {
imports.push_back(import2); imports.push_back(import2);
return secondType; return secondType;
}); });
ON_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _)) ON_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _))
.WillByDefault([&](auto, auto &imports, auto) { .WillByDefault([&](auto, auto &imports, auto, auto) {
imports.push_back(import3); imports.push_back(import3);
return thirdType; return thirdType;
}); });
@@ -239,7 +239,7 @@ protected:
SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/types/example2.qmltypes"); SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/types/example2.qmltypes");
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir"); SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml"); SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml"); SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml");
SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
ModuleId qmlModuleId{storage.moduleId("Qml")}; ModuleId qmlModuleId{storage.moduleId("Qml")};
ModuleId qmlCppNativeModuleId{storage.moduleId("Qml-cppnative")}; ModuleId qmlCppNativeModuleId{storage.moduleId("Qml-cppnative")};
@@ -249,6 +249,8 @@ protected:
ModuleId builtinCppNativeModuleId{storage.moduleId("QML-cppnative")}; ModuleId builtinCppNativeModuleId{storage.moduleId("QML-cppnative")};
ModuleId quickModuleId{storage.moduleId("Quick")}; ModuleId quickModuleId{storage.moduleId("Quick")};
ModuleId quickCppNativeModuleId{storage.moduleId("Quick-cppnative")}; ModuleId quickCppNativeModuleId{storage.moduleId("Quick-cppnative")};
ModuleId pathModuleId{storage.moduleId("/path")};
ModuleId subPathQmlModuleId{storage.moduleId("/path/qml")};
Storage::Type objectType{"QObject", Storage::Type objectType{"QObject",
Storage::ImportedType{}, Storage::ImportedType{},
Storage::TypeAccessSemantics::Reference, Storage::TypeAccessSemantics::Reference,
@@ -397,6 +399,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
EXPECT_CALL(projectStorageMock, moduleId(Eq("Example"))); EXPECT_CALL(projectStorageMock, moduleId(Eq("Example")));
EXPECT_CALL(projectStorageMock, moduleId(Eq("Example-cppnative"))); EXPECT_CALL(projectStorageMock, moduleId(Eq("Example-cppnative")));
EXPECT_CALL(projectStorageMock, moduleId(Eq("/path")));
EXPECT_CALL(projectStorageMock, EXPECT_CALL(projectStorageMock,
synchronize( synchronize(
AllOf(Field(&SynchronizationPackage::imports, ElementsAre(import)), AllOf(Field(&SynchronizationPackage::imports, ElementsAre(import)),
@@ -445,14 +448,14 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments)
.WillByDefault(Return(qmlDocument3)); .WillByDefault(Return(qmlDocument3));
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstTypeV2 2.2 First.2.qml FirstTypeV2 2.2 First2.qml
SecondType 2.1 OldSecond.qml SecondType 2.1 OldSecond.qml
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillRepeatedly(Return(qmldir)); .WillRepeatedly(Return(qmldir));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First2.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))));
@@ -463,7 +466,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocuments)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstTypeV2 2.2 First.2.qml FirstTypeV2 2.2 First2.qml
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
QString qmlDocument1{"First{}"}; QString qmlDocument1{"First{}"};
QString qmlDocument2{"Second{}"}; QString qmlDocument2{"Second{}"};
@@ -471,14 +474,14 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocuments)
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
.WillByDefault(Return(qmlDocument1)); .WillByDefault(Return(qmlDocument1));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First2.qml"))))
.WillByDefault(Return(qmlDocument2)); .WillByDefault(Return(qmlDocument2));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
.WillByDefault(Return(qmlDocument3)); .WillByDefault(Return(qmlDocument3));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _)); EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _, _, _));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _)); EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _)); EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _));
updater.update(qmlDirs, {}); updater.update(qmlDirs, {});
} }
@@ -496,7 +499,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstType 2.2 First.2.qml FirstType 2.2 First2.qml
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
@@ -512,21 +515,24 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
qmlDocumentSourceId1, qmlDocumentSourceId1,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0),
AllOf(IsStorageType("First.2.qml", IsExportedType(pathModuleId, "First", -1, -1)))),
AllOf(IsStorageType("First2.qml",
Storage::ImportedType{"Object2"}, Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId2, qmlDocumentSourceId2,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2),
IsExportedType(pathModuleId, "First2", -1, -1)))),
AllOf(IsStorageType("Second.qml", AllOf(IsStorageType("Second.qml",
Storage::ImportedType{"Object3"}, Storage::ImportedType{"Object3"},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId3, qmlDocumentSourceId3,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2)))))), ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2),
IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
@@ -565,7 +571,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeRemoved)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstType 2.2 First.2.qml FirstType 2.2 First2.qml
typeinfo example.qmltypes typeinfo example.qmltypes
typeinfo types/example2.qmltypes typeinfo types/example2.qmltypes
)"}; )"};
@@ -595,14 +601,16 @@ TEST_F(ProjectStorageUpdater, SynchronizeRemoved)
qmlDocumentSourceId1, qmlDocumentSourceId1,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0),
AllOf(IsStorageType("First.2.qml", IsExportedType(pathModuleId, "First", -1, -1)))),
AllOf(IsStorageType("First2.qml",
Storage::ImportedType{}, Storage::ImportedType{},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId2, qmlDocumentSourceId2,
Storage::ChangeLevel::Minimal), Storage::ChangeLevel::Minimal),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2),
IsExportedType(pathModuleId, "First2", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, UnorderedElementsAre(qmlDirPathSourceId,
qmltypesPathSourceId, qmltypesPathSourceId,
@@ -645,7 +653,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.0 First.qml FirstType 1.0 First.qml
FirstType 2.2 First.2.qml FirstType 2.2 First2.qml
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3)))
@@ -663,21 +671,24 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
qmlDocumentSourceId1, qmlDocumentSourceId1,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0),
AllOf(IsStorageType("First.2.qml", IsExportedType(pathModuleId, "First", -1, -1)))),
AllOf(IsStorageType("First2.qml",
Storage::ImportedType{"Object2"}, Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId2, qmlDocumentSourceId2,
Storage::ChangeLevel::Full), Storage::ChangeLevel::Full),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))), ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2),
IsExportedType(pathModuleId, "First2", -1, -1)))),
AllOf(IsStorageType("Second.qml", AllOf(IsStorageType("Second.qml",
Storage::ImportedType{}, Storage::ImportedType{},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId3, qmlDocumentSourceId3,
Storage::ChangeLevel::Minimal), Storage::ChangeLevel::Minimal),
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2)))))), ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2),
IsExportedType(pathModuleId, "Second", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1, qmlDocumentSourceId1,
@@ -712,7 +723,7 @@ TEST_F(ProjectStorageUpdater, UpdateQmldirDocuments)
{ {
QString qmldir{R"(module Example QString qmldir{R"(module Example
FirstType 1.1 First.qml FirstType 1.1 First.qml
FirstType 2.2 First.2.qml FirstType 2.2 First2.qml
SecondType 2.2 Second.qml)"}; SecondType 2.2 Second.qml)"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3)))
@@ -767,7 +778,7 @@ TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChanged)
qmlDocumentSourceId1, qmlDocumentSourceId1,
Storage::ChangeLevel::ExcludeExportedTypes), Storage::ChangeLevel::ExcludeExportedTypes),
Field(&Storage::Type::exportedTypes, IsEmpty())), Field(&Storage::Type::exportedTypes, IsEmpty())),
AllOf(IsStorageType("First.2.qml", AllOf(IsStorageType("First2.qml",
Storage::ImportedType{"Object2"}, Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId2, qmlDocumentSourceId2,
@@ -921,7 +932,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentVersionButSame
UnorderedElementsAre( UnorderedElementsAre(
IsExportedType(exampleModuleId, "FirstType", 1, 0), IsExportedType(exampleModuleId, "FirstType", 1, 0),
IsExportedType(exampleModuleId, "FirstType", 1, 1), IsExportedType(exampleModuleId, "FirstType", 1, 1),
IsExportedType(exampleModuleId, "FirstType", 6, 0)))))), IsExportedType(exampleModuleId, "FirstType", 6, 0),
IsExportedType(pathModuleId, "First", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,
@@ -951,8 +963,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSam
synchronize( synchronize(
AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)),
Field(&SynchronizationPackage::types, Field(&SynchronizationPackage::types,
UnorderedElementsAre(AllOf( UnorderedElementsAre(
IsStorageType("First.qml", AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"}, Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference, TypeAccessSemantics::Reference,
qmlDocumentSourceId1, qmlDocumentSourceId1,
@@ -960,7 +972,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSam
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
UnorderedElementsAre( UnorderedElementsAre(
IsExportedType(exampleModuleId, "FirstType", 1, 0), IsExportedType(exampleModuleId, "FirstType", 1, 0),
IsExportedType(exampleModuleId, "FirstType2", 1, 0)))))), IsExportedType(exampleModuleId, "FirstType2", 1, 0),
IsExportedType(pathModuleId, "First", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,
@@ -1032,7 +1045,8 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithRelativeFilePath)
Field(&Storage::Type::exportedTypes, Field(&Storage::Type::exportedTypes,
UnorderedElementsAre( UnorderedElementsAre(
IsExportedType(exampleModuleId, "FirstType", 1, 0), IsExportedType(exampleModuleId, "FirstType", 1, 0),
IsExportedType(exampleModuleId, "FirstType2", 1, 0)))))), IsExportedType(exampleModuleId, "FirstType2", 1, 0),
IsExportedType(subPathQmlModuleId, "First", -1, -1)))))),
Field(&SynchronizationPackage::updatedSourceIds, Field(&SynchronizationPackage::updatedSourceIds,
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)), UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)),
Field(&SynchronizationPackage::updatedFileStatusSourceIds, Field(&SynchronizationPackage::updatedFileStatusSourceIds,

View File

@@ -133,12 +133,13 @@ protected:
Storage::Imports imports; Storage::Imports imports;
SourceId qmlFileSourceId{sourcePathCache.sourceId("/path/to/qmlfile.qml")}; SourceId qmlFileSourceId{sourcePathCache.sourceId("/path/to/qmlfile.qml")};
SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)}; SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)};
ModuleId directoryModuleId{storage.moduleId("/path/to")}; Utils::PathString directoryPath{sourcePathCache.sourceContextPath(qmlFileSourceContextId)};
ModuleId directoryModuleId{storage.moduleId(directoryPath)};
}; };
TEST_F(QmlDocumentParser, Prototype) TEST_F(QmlDocumentParser, Prototype)
{ {
auto type = parser.parse("Example{}", imports, qmlFileSourceId); auto type = parser.parse("Example{}", imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example"))); ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example")));
} }
@@ -149,7 +150,7 @@ TEST_F(QmlDocumentParser, QualifiedPrototype)
QString text = R"(import Example 2.1 as Example QString text = R"(import Example 2.1 as Example
Example.Item{})"; Example.Item{})";
auto type = parser.parse(text, imports, qmlFileSourceId); auto type = parser.parse(text, imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type, ASSERT_THAT(type,
HasPrototype(Storage::QualifiedImportedType("Item", HasPrototype(Storage::QualifiedImportedType("Item",
@@ -160,7 +161,7 @@ TEST_F(QmlDocumentParser, QualifiedPrototype)
TEST_F(QmlDocumentParser, Properties) TEST_F(QmlDocumentParser, Properties)
{ {
auto type = parser.parse(R"(Example{ property int foo })", imports, qmlFileSourceId); auto type = parser.parse(R"(Example{ property int foo })", imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type.propertyDeclarations, ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration("foo", UnorderedElementsAre(IsPropertyDeclaration("foo",
@@ -175,7 +176,8 @@ TEST_F(QmlDocumentParser, QualifiedProperties)
auto type = parser.parse(R"(import Example 2.1 as Example auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Example.Foo foo})", Item{ property Example.Foo foo})",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations, ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration( UnorderedElementsAre(IsPropertyDeclaration(
@@ -192,7 +194,8 @@ TEST_F(QmlDocumentParser, EnumerationInProperties)
auto type = parser.parse(R"(import Example 2.1 as Example auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Enumeration.Foo foo})", Item{ property Enumeration.Foo foo})",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations, ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration("foo", UnorderedElementsAre(IsPropertyDeclaration("foo",
@@ -207,7 +210,8 @@ TEST_F(QmlDocumentParser, QualifiedEnumerationInProperties)
auto type = parser.parse(R"(import Example 2.1 as Example auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Example.Enumeration.Foo foo})", Item{ property Example.Enumeration.Foo foo})",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations, ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration( UnorderedElementsAre(IsPropertyDeclaration(
@@ -223,21 +227,61 @@ TEST_F(QmlDocumentParser, Imports)
{ {
ModuleId fooDirectoryModuleId = storage.moduleId("/path/foo"); ModuleId fooDirectoryModuleId = storage.moduleId("/path/foo");
ModuleId qmlModuleId = storage.moduleId("QML"); ModuleId qmlModuleId = storage.moduleId("QML");
ModuleId qtQmlModuleId = storage.moduleId("QtQml");
ModuleId qtQuickModuleId = storage.moduleId("QtQuick"); ModuleId qtQuickModuleId = storage.moduleId("QtQuick");
auto type = parser.parse(R"(import QtQuick auto type = parser.parse(R"(import QtQuick
import "../foo" import "../foo"
Example{})", Example{})",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(imports, ASSERT_THAT(imports,
UnorderedElementsAre( UnorderedElementsAre(
Storage::Import{directoryModuleId, Storage::Version{}, qmlFileSourceId}, Storage::Import{directoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{fooDirectoryModuleId, Storage::Version{}, qmlFileSourceId}, Storage::Import{fooDirectoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qmlModuleId, Storage::Version{1, 0}, qmlFileSourceId}, Storage::Import{qmlModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qtQmlModuleId, Storage::Version{6, 0}, qmlFileSourceId}, Storage::Import{qtQuickModuleId, Storage::Version{}, qmlFileSourceId}));
}
TEST_F(QmlDocumentParser, ImportsWithVersion)
{
ModuleId fooDirectoryModuleId = storage.moduleId("/path/foo");
ModuleId qmlModuleId = storage.moduleId("QML");
ModuleId qtQuickModuleId = storage.moduleId("QtQuick");
auto type = parser.parse(R"(import QtQuick 2.1
import "../foo"
Example{})",
imports,
qmlFileSourceId,
directoryPath);
ASSERT_THAT(imports,
UnorderedElementsAre(
Storage::Import{directoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{fooDirectoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qmlModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qtQuickModuleId, Storage::Version{2, 1}, qmlFileSourceId}));
}
TEST_F(QmlDocumentParser, ImportsWithExplictDirectory)
{
ModuleId qmlModuleId = storage.moduleId("QML");
ModuleId qtQuickModuleId = storage.moduleId("QtQuick");
auto type = parser.parse(R"(import QtQuick
import "../to"
import "."
Example{})",
imports,
qmlFileSourceId,
directoryPath);
ASSERT_THAT(
imports,
UnorderedElementsAre(Storage::Import{directoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qmlModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qtQuickModuleId, Storage::Version{}, qmlFileSourceId})); Storage::Import{qtQuickModuleId, Storage::Version{}, qmlFileSourceId}));
} }
@@ -246,7 +290,8 @@ TEST_F(QmlDocumentParser, Functions)
auto type = parser.parse( auto type = parser.parse(
"Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}", "Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.functionDeclarations, ASSERT_THAT(type.functionDeclarations,
UnorderedElementsAre(AllOf(IsFunctionDeclaration("otherFunction", ""), UnorderedElementsAre(AllOf(IsFunctionDeclaration("otherFunction", ""),
@@ -261,7 +306,8 @@ TEST_F(QmlDocumentParser, Signals)
{ {
auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}", auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.signalDeclarations, ASSERT_THAT(type.signalDeclarations,
UnorderedElementsAre(AllOf(IsSignalDeclaration("someSignal"), UnorderedElementsAre(AllOf(IsSignalDeclaration("someSignal"),
@@ -277,7 +323,8 @@ TEST_F(QmlDocumentParser, Enumeration)
auto type = parser.parse("Example{\n enum Color{red, green, blue=10, white}\n enum " auto type = parser.parse("Example{\n enum Color{red, green, blue=10, white}\n enum "
"State{On,Off}\n}", "State{On,Off}\n}",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.enumerationDeclarations, ASSERT_THAT(type.enumerationDeclarations,
UnorderedElementsAre( UnorderedElementsAre(
@@ -308,7 +355,8 @@ TEST_F(QmlDocumentParser, DISABLED_DuplicateImportsAreRemoved)
Example{})", Example{})",
imports, imports,
qmlFileSourceId); qmlFileSourceId,
directoryPath);
ASSERT_THAT(imports, ASSERT_THAT(imports,
UnorderedElementsAre( UnorderedElementsAre(

View File

@@ -36,6 +36,7 @@ public:
parse, parse,
(const QString &sourceContent, (const QString &sourceContent,
QmlDesigner::Storage::Imports &imports, QmlDesigner::Storage::Imports &imports,
QmlDesigner::SourceId sourceId), QmlDesigner::SourceId sourceId,
Utils::SmallStringView directoryPath),
(override)); (override));
}; };