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

View File

@@ -1,3 +1,4 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
@@ -54,16 +55,20 @@ Storage::Version convertVersion(QmlDom::Version version)
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{
std::u16string_view{localPath.utf16(), static_cast<std::size_t>(localPath.size())}};
modulePath /= relativePath.toStdString();
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,
@@ -71,21 +76,26 @@ Storage::Import createImport(const QmlDom::Import &qmlImport,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
if (qmlImport.uri == u"file://.") {
auto moduleId = storage.moduleId(directoryPath);
using QmlUriKind = QQmlJS::Dom::QmlUri::Kind;
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);
}
if (qmlImport.uri.startsWith(u"file://")) {
auto moduleId = storage.moduleId(convertUri(qmlImport.uri));
return Storage::Import(moduleId, Storage::Version{}, sourceId);
if (uri.kind() == QmlUriKind::ModuleUri) {
auto moduleId = storage.moduleId(Utils::PathString{uri.moduleUri()});
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);
}
QualifiedImports filterQualifiedImports(const QList<QmlDom::Import> &qmlImports,
QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
SourceId sourceId,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
@@ -93,7 +103,7 @@ QualifiedImports filterQualifiedImports(const QList<QmlDom::Import> &qmlImports,
QualifiedImports qualifiedImports;
for (const QmlDom::Import &qmlImport : qmlImports) {
if (!qmlImport.importId.isEmpty())
if (!qmlImport.importId.isEmpty() && !qmlImport.implicit)
qualifiedImports.try_emplace(qmlImport.importId,
createImport(qmlImport, sourceId, directoryPath, storage));
}
@@ -107,11 +117,24 @@ void addImports(Storage::Imports &imports,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
for (const QmlDom::Import &qmlImport : qmlImports)
imports.push_back(createImport(qmlImport, sourceId, directoryPath, storage));
int importCount = 0;
for (const QmlDom::Import &qmlImport : qmlImports) {
if (!qmlImport.implicit) {
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 begin = std::prev(end, qmlImports.size());
auto begin = std::prev(end, importCount);
std::sort(begin, 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::Imports &imports,
SourceId sourceId)
SourceId sourceId,
Utils::SmallStringView directoryPath)
{
Storage::Type type;
QmlDom::DomItem environment = QmlDom::DomEnvironment::create(
{},
QmlDom::DomEnvironment::Option::SingleThreaded
| QmlDom::DomEnvironment::Option::NoDependencies);
using Option = QmlDom::DomEnvironment::Option;
QmlDom::DomItem environment = QmlDom::DomEnvironment::create({},
Option::SingleThreaded
| Option::NoDependencies
| Option::WeakLoad);
QmlDom::DomItem items;
@@ -238,9 +264,11 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
const QmlDom::QmlObject &qmlObject = objects.front();
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);

View File

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

View File

@@ -34,7 +34,11 @@ namespace QmlDesigner {
class QmlDocumentParserInterface
{
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:
~QmlDocumentParserInterface() = default;

View File

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

View File

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

View File

@@ -133,12 +133,13 @@ protected:
Storage::Imports imports;
SourceId qmlFileSourceId{sourcePathCache.sourceId("/path/to/qmlfile.qml")};
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)
{
auto type = parser.parse("Example{}", imports, qmlFileSourceId);
auto type = parser.parse("Example{}", imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example")));
}
@@ -149,7 +150,7 @@ TEST_F(QmlDocumentParser, QualifiedPrototype)
QString text = R"(import Example 2.1 as Example
Example.Item{})";
auto type = parser.parse(text, imports, qmlFileSourceId);
auto type = parser.parse(text, imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type,
HasPrototype(Storage::QualifiedImportedType("Item",
@@ -160,7 +161,7 @@ TEST_F(QmlDocumentParser, QualifiedPrototype)
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,
UnorderedElementsAre(IsPropertyDeclaration("foo",
@@ -175,7 +176,8 @@ TEST_F(QmlDocumentParser, QualifiedProperties)
auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Example.Foo foo})",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration(
@@ -192,7 +194,8 @@ TEST_F(QmlDocumentParser, EnumerationInProperties)
auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Enumeration.Foo foo})",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration("foo",
@@ -207,7 +210,8 @@ TEST_F(QmlDocumentParser, QualifiedEnumerationInProperties)
auto type = parser.parse(R"(import Example 2.1 as Example
Item{ property Example.Enumeration.Foo foo})",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration(
@@ -223,30 +227,71 @@ TEST_F(QmlDocumentParser, Imports)
{
ModuleId fooDirectoryModuleId = storage.moduleId("/path/foo");
ModuleId qmlModuleId = storage.moduleId("QML");
ModuleId qtQmlModuleId = storage.moduleId("QtQml");
ModuleId qtQuickModuleId = storage.moduleId("QtQuick");
auto type = parser.parse(R"(import QtQuick
import "../foo"
Example{})",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(imports,
UnorderedElementsAre(
Storage::Import{directoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{fooDirectoryModuleId, Storage::Version{}, qmlFileSourceId},
Storage::Import{qmlModuleId, Storage::Version{1, 0}, qmlFileSourceId},
Storage::Import{qtQmlModuleId, Storage::Version{6, 0}, qmlFileSourceId},
Storage::Import{qmlModuleId, Storage::Version{}, 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}));
}
TEST_F(QmlDocumentParser, Functions)
{
auto type = parser.parse(
"Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.functionDeclarations,
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}",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.signalDeclarations,
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 "
"State{On,Off}\n}",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(type.enumerationDeclarations,
UnorderedElementsAre(
@@ -308,7 +355,8 @@ TEST_F(QmlDocumentParser, DISABLED_DuplicateImportsAreRemoved)
Example{})",
imports,
qmlFileSourceId);
qmlFileSourceId,
directoryPath);
ASSERT_THAT(imports,
UnorderedElementsAre(

View File

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