QmlDesigner: Support multiple module ids per type

The type will be use source id and name instead of module id and name as
key.

Task-number: QDS-5236
Task-number: QDS-5238
Change-Id: Ibc9c298dc0a6363b630173ec4981d574cecd02ff
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marco Bubke
2021-10-11 11:15:47 +02:00
committed by Tim Jenssen
parent 3871e40f43
commit cb946ec307
16 changed files with 1835 additions and 2206 deletions

View File

@@ -99,6 +99,24 @@ bool set_intersection_compare(
return false;
}
template<class InputIt1, class InputIt2, class Callable, class Compare>
void set_greedy_difference(
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable call, Compare comp)
{
while (first1 != last1 && first2 != last2) {
if (comp(*first1, *first2)) {
call(*first1++);
} else if (comp(*first2, *first1)) {
++first2;
} else {
++first1;
}
}
while (first1 != last1)
call(*first1++);
}
template<typename InputIt1, typename InputIt2, typename BinaryPredicate, typename Callable, typename Value>
Value mismatch_collect(InputIt1 first1,
InputIt1 last1,

View File

@@ -33,13 +33,14 @@ namespace QmlDesigner {
class ProjectStorageInterface
{
public:
virtual void synchronize(Storage::Modules modules,
Storage::Imports imports,
virtual void synchronize(Storage::Imports imports,
Storage::Types types,
SourceIds sourceIds,
FileStatuses fileStatuses)
= 0;
virtual ModuleId moduleId(Utils::SmallStringView name) = 0;
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
virtual SourceIds fetchSourceDependencieIds(SourceId sourceId) const = 0;

View File

@@ -121,38 +121,6 @@ public:
VersionNumber minor;
};
class Module
{
public:
explicit Module() = default;
explicit Module(Utils::SmallStringView name, SourceId sourceId = SourceId{})
: name{name}
, sourceId{sourceId}
{}
explicit Module(QStringView name, SourceId sourceId = SourceId{})
: name{name}
, sourceId{sourceId}
{}
explicit Module(Utils::SmallStringView name, int sourceId)
: name{name}
, sourceId{sourceId}
{}
friend bool operator==(const Module &first, const Module &second)
{
return first.name == second.name;
}
public:
Utils::PathString name;
SourceId sourceId;
};
using Modules = std::vector<Module>;
enum class IsQualified : int { No, Yes };
inline int operator-(IsQualified first, IsQualified second)
@@ -172,41 +140,29 @@ class Import
public:
explicit Import() = default;
explicit Import(Utils::SmallStringView name,
Version version,
SourceId sourceId,
ImportKind kind = ImportKind::Module)
: name{name}
, version{version}
, sourceId{sourceId}
, kind{kind}
{}
explicit Import(Version version, ModuleId moduleId, SourceId sourceId)
explicit Import(ModuleId moduleId, Version version, SourceId sourceId)
: version{version}
, moduleId{moduleId}
, sourceId{sourceId}
{}
explicit Import(Utils::SmallStringView name, int majorVersion, int minorVersion, int sourceId)
: name{name}
explicit Import(int moduleId, int majorVersion, int minorVersion, int sourceId)
: moduleId{moduleId}
, version{majorVersion, minorVersion}
, sourceId{sourceId}
{}
friend bool operator==(const Import &first, const Import &second)
{
return first.name == second.name && first.version == second.version
&& first.sourceId == second.sourceId && first.moduleId.id == second.moduleId.id;
return first.moduleId == second.moduleId && first.version == second.version
&& first.sourceId == second.sourceId;
}
public:
Utils::SmallString name;
Version version;
ModuleId moduleId;
SourceId sourceId;
Utils::SmallString aliasName;
ImportKind kind = ImportKind::Module;
};
using Imports = std::vector<Import>;
@@ -296,9 +252,10 @@ public:
, moduleId{moduleId}
{}
explicit ExportedType(Utils::SmallStringView name, int majorVersion, int minorVersion)
explicit ExportedType(int moduleId, Utils::SmallStringView name, int majorVersion, int minorVersion)
: name{name}
, version{majorVersion, minorVersion}
, moduleId{moduleId}
{}
friend bool operator==(const ExportedType &first, const ExportedType &second)
@@ -576,6 +533,15 @@ public:
, kind{PropertyKind::Property}
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
TypeId propertyTypeId,
PropertyDeclarationTraits traits)
: name{name}
, traits{traits}
, propertyTypeId{propertyTypeId}
, kind{PropertyKind::Property}
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
ImportedTypeName typeName,
PropertyDeclarationTraits traits,
@@ -588,13 +554,24 @@ public:
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
Utils::SmallStringView typeName,
TypeId propetyTypeId,
PropertyDeclarationTraits traits,
Utils::SmallStringView aliasPropertyName)
: name{name}
, aliasPropertyName{aliasPropertyName}
, traits{traits}
, propertyTypeId{propertyTypeId}
, kind{PropertyKind::Property}
{}
explicit PropertyDeclaration(Utils::SmallStringView name,
long long propertyTypeId,
int traits,
Utils::SmallStringView aliasPropertyName)
: name{name}
, typeName{NativeType{typeName}}
, aliasPropertyName{aliasPropertyName}
, traits{static_cast<PropertyDeclarationTraits>(traits)}
, propertyTypeId{propertyTypeId}
, kind{PropertyKind::Property}
{}
@@ -619,6 +596,7 @@ public:
ImportedTypeName typeName;
Utils::SmallString aliasPropertyName;
PropertyDeclarationTraits traits = {};
TypeId propertyTypeId;
TypeId typeId;
PropertyKind kind = PropertyKind::Property;
};
@@ -657,8 +635,7 @@ class Type
{
public:
explicit Type() = default;
explicit Type(ModuleId moduleId,
Utils::SmallStringView typeName,
explicit Type(Utils::SmallStringView typeName,
ImportedTypeName prototype,
TypeAccessSemantics accessSemantics,
SourceId sourceId,
@@ -677,12 +654,20 @@ public:
, enumerationDeclarations{std::move(enumerationDeclarations)}
, accessSemantics{accessSemantics}
, sourceId{sourceId}
, moduleId{moduleId}
, changeLevel{changeLevel}
{}
explicit Type(ModuleId moduleId,
Utils::SmallStringView typeName,
explicit Type(Utils::SmallStringView typeName,
TypeId prototypeId,
TypeAccessSemantics accessSemantics,
SourceId sourceId)
: typeName{typeName}
, accessSemantics{accessSemantics}
, sourceId{sourceId}
, prototypeId{prototypeId}
{}
explicit Type(Utils::SmallStringView typeName,
Utils::SmallStringView prototype,
int accessSemantics,
int sourceId)
@@ -690,22 +675,19 @@ public:
, prototype{NativeType{prototype}}
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
, moduleId{moduleId}
{}
explicit Type(int moduleId,
explicit Type(int sourceId,
Utils::SmallStringView typeName,
long long typeId,
Utils::SmallStringView prototype,
int accessSemantics,
int sourceId)
long long prototypeId,
int accessSemantics)
: typeName{typeName}
, prototype{NativeType{prototype}}
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
, typeId{typeId}
, moduleId{moduleId}
, prototypeId{prototypeId}
{}
friend bool operator==(const Type &first, const Type &second) noexcept
@@ -715,7 +697,6 @@ public:
&& first.propertyDeclarations == second.propertyDeclarations
&& first.functionDeclarations == second.functionDeclarations
&& first.signalDeclarations == second.signalDeclarations
&& first.moduleId == second.moduleId && first.sourceId == second.sourceId
&& first.sourceId == second.sourceId;
}
@@ -730,28 +711,10 @@ public:
TypeAccessSemantics accessSemantics = TypeAccessSemantics::None;
SourceId sourceId;
TypeId typeId;
ModuleId moduleId;
TypeId prototypeId;
ChangeLevel changeLevel = ChangeLevel::Full;
};
using Types = std::vector<Type>;
class ModuleView
{
public:
explicit ModuleView(Utils::SmallStringView name, int sourceId)
: name{name}
, sourceId{sourceId}
{}
friend bool operator==(const ModuleView &first, const ModuleView &second)
{
return first.name == second.name && first.sourceId == second.sourceId;
}
public:
Utils::SmallStringView name;
SourceId sourceId;
};
} // namespace QmlDesigner::Storage

View File

@@ -52,7 +52,6 @@ ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirPa
void ProjectUpdater::update()
{
Storage::Modules modules;
Storage::Imports imports;
Storage::Types types;
SourceIds sourceIds;
@@ -67,22 +66,17 @@ void ProjectUpdater::update()
QmlDirParser parser;
parser.parse(m_fileSystem.contentAsQString(qmldirPath));
modules.emplace_back(parser.typeNamespace(), qmlDirSourceId);
sourceIds.push_back(qmlDirSourceId);
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
parseTypeInfos(parser.typeInfos(),
directoryId,
ModuleId{&qmlDirSourceId},
imports,
types,
sourceIds,
fileStatuses);
ModuleId moduleId = m_projectStorage.moduleId(Utils::PathString{parser.typeNamespace()});
parseTypeInfos(
parser.typeInfos(), directoryId, moduleId, imports, types, sourceIds, fileStatuses);
parseQmlComponents(createComponentReferences(parser.components()),
directoryId,
ModuleId{&qmlDirSourceId},
moduleId,
imports,
types,
sourceIds,
@@ -106,8 +100,7 @@ void ProjectUpdater::update()
}
}
m_projectStorage.synchronize(std::move(modules),
std::move(imports),
m_projectStorage.synchronize(std::move(imports),
std::move(types),
std::move(sourceIds),
std::move(fileStatuses));
@@ -197,11 +190,11 @@ void ProjectUpdater::parseQmlComponents(ComponentReferences components,
auto type = m_qmlDocumentParser.parse(content, imports);
type.typeName = fileName;
type.moduleId = moduleId;
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
type.sourceId = sourceId;
type.exportedTypes.push_back(
Storage::ExportedType{Utils::SmallString{component.typeName},
Storage::ExportedType{moduleId,
Utils::SmallString{component.typeName},
Storage::Version{component.majorVersion, component.minorVersion}});
types.push_back(std::move(type));

View File

@@ -69,19 +69,19 @@ void addImports(Storage::Imports &imports,
const QList<QmlDom::Import> &qmlImports,
SourceId sourceId,
SourceContextId sourceContextId,
QmlDocumentParser::PathCache &pathCache)
QmlDocumentParser::PathCache &pathCache,
QmlDocumentParser::ProjectStorage &storage)
{
for (const QmlDom::Import &qmlImport : qmlImports) {
if (qmlImport.uri == u"file://.") {
SourceId directorySourceId = pathCache.sourceId(sourceContextId, ".");
imports.emplace_back(Storage::Version{}, ModuleId{&directorySourceId}, sourceId);
auto moduleId = storage.moduleId(pathCache.sourceContextPath(sourceContextId));
imports.emplace_back(moduleId, Storage::Version{}, sourceId);
} else if (qmlImport.uri.startsWith(u"file://")) {
SourceId uriSourceId = pathCache.sourceId(sourceContextId, convertUri(qmlImport.uri));
imports.emplace_back(Storage::Version{}, ModuleId{&uriSourceId}, sourceId);
auto moduleId = storage.moduleId(convertUri(qmlImport.uri));
imports.emplace_back(moduleId, Storage::Version{}, sourceId);
} else {
imports.emplace_back(Utils::SmallString{qmlImport.uri},
convertVersion(qmlImport.version),
sourceId);
auto moduleId = storage.moduleId(Utils::SmallString{qmlImport.uri});
imports.emplace_back(moduleId, convertVersion(qmlImport.version), sourceId);
}
}
}
@@ -185,7 +185,7 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
type.prototype = Storage::ImportedType{Utils::SmallString{qmlObject.name()}};
addImports(imports, qmlFile->imports(), sourceId, sourceContextId, m_pathCache);
addImports(imports, qmlFile->imports(), sourceId, sourceContextId, m_pathCache, m_storage);
addPropertyDeclarations(type, qmlObject);
addFunctionAndSignalDeclarations(type, qmlObject);

View File

@@ -43,11 +43,12 @@ class SourcePathCache;
class QmlDocumentParser
{
public:
using PathCache = QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>,
NonLockingMutex>;
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
QmlDocumentParser(PathCache &pathCache)
QmlDocumentParser(PathCache &pathCache, ProjectStorage &storage)
: m_pathCache{pathCache}
, m_storage{storage}
{}
virtual Storage::Type parse(const QString &sourceContent,
@@ -57,5 +58,6 @@ public:
private:
PathCache &m_pathCache;
ProjectStorage &m_storage;
};
} // namespace QmlDesigner

View File

@@ -45,15 +45,20 @@ namespace QmlDom = QQmlJS::Dom;
namespace {
void addType(const QQmlJSScope::Ptr &object, Storage::Types &types) {}
Storage::Import createImport(const QString &dependency, SourceId sourceId)
void appendImports(Storage::Imports &imports,
const QString &dependency,
SourceId sourceId,
QmlTypesParser::ProjectStorage &storage)
{
Storage::Import import;
import.kind = Storage::ImportKind::QmlTypesDependency;
import.sourceId = sourceId;
auto spaceFound = std::find_if(dependency.begin(), dependency.end(), [](QChar c) {
return c.isSpace();
});
import.name = Utils::SmallString{QStringView(dependency.begin(), spaceFound)};
Utils::PathString moduleName{QStringView(dependency.begin(), spaceFound)};
ModuleId moduleId = storage.moduleId(moduleName);
moduleName.append("-cppnative");
ModuleId cppModuleId = storage.moduleId(moduleName);
auto majorVersionFound = std::find_if(spaceFound, dependency.end(), [](QChar c) {
return c.isDigit();
@@ -61,10 +66,12 @@ Storage::Import createImport(const QString &dependency, SourceId sourceId)
auto majorVersionEnd = std::find_if(majorVersionFound, dependency.end(), [](QChar c) {
return !c.isDigit();
});
Storage::Version version;
QStringView majorVersionString(majorVersionFound, majorVersionEnd);
if (majorVersionString.isEmpty())
return import;
import.version.major.value = majorVersionString.toInt();
if (!majorVersionString.isEmpty()) {
version.major.value = majorVersionString.toInt();
auto minorVersionFound = std::find_if(majorVersionEnd, dependency.end(), [](QChar c) {
return c.isDigit();
@@ -73,21 +80,25 @@ Storage::Import createImport(const QString &dependency, SourceId sourceId)
return !c.isDigit();
});
QStringView minorVersionString(minorVersionFound, minorVersionEnd);
if (minorVersionString.isEmpty())
return import;
import.version.minor.value = QStringView(minorVersionFound, minorVersionEnd).toInt();
return import;
}
void addImports(Storage::Imports &imports, SourceId sourceId, const QStringList &dependencies)
{
for (const QString &dependency : dependencies) {
imports.push_back(createImport(dependency, sourceId));
if (!minorVersionString.isEmpty())
version.minor.value = QStringView(minorVersionFound, minorVersionEnd).toInt();
}
imports.emplace_back("QML", Storage::Version{}, sourceId, Storage::ImportKind::QmlTypesDependency);
imports.emplace_back("QtQml", Storage::Version{}, sourceId, Storage::ImportKind::QmlTypesDependency);
imports.emplace_back(moduleId, version, sourceId);
imports.emplace_back(cppModuleId, version, sourceId);
}
void addImports(Storage::Imports &imports,
SourceId sourceId,
const QStringList &dependencies,
QmlTypesParser::ProjectStorage &storage)
{
for (const QString &dependency : dependencies)
appendImports(imports, dependency, sourceId, storage);
imports.emplace_back(storage.moduleId("QML"), Storage::Version{}, sourceId);
imports.emplace_back(storage.moduleId("QtQml"), Storage::Version{}, sourceId);
imports.emplace_back(storage.moduleId("QtQml-cppnative"), Storage::Version{}, sourceId);
}
Storage::TypeAccessSemantics createTypeAccessSemantics(QQmlJSScope::AccessSemantics accessSematics)
@@ -249,8 +260,7 @@ Storage::EnumerationDeclarations createEnumeration(const QHash<QString, QQmlJSMe
void addType(Storage::Types &types, SourceId sourceId, ModuleId moduleId, const QQmlJSScope &component)
{
auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals(component.ownMethods());
types.emplace_back(moduleId,
Utils::SmallString{component.internalName()},
types.emplace_back(Utils::SmallString{component.internalName()},
Storage::NativeType{Utils::SmallString{component.baseTypeName()}},
createTypeAccessSemantics(component.accessSemantics()),
sourceId,
@@ -287,7 +297,7 @@ void QmlTypesParser::parse(const QString &sourceContent,
if (!isValid)
throw CannotParseQmlTypesFile{};
addImports(imports, sourceId, dependencies);
addImports(imports, sourceId, dependencies, m_storage);
addTypes(types, sourceId, moduleId, components);
}

View File

@@ -43,11 +43,12 @@ class SourcePathCache;
class QmlTypesParser : public QmlTypesParserInterface
{
public:
using PathCache = QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>,
NonLockingMutex>;
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
QmlTypesParser(PathCache &pathCache)
QmlTypesParser(PathCache &pathCache, ProjectStorage &storage)
: m_pathCache{pathCache}
, m_storage{storage}
{}
void parse(const QString &sourceContent,
@@ -58,5 +59,6 @@ public:
private:
PathCache &m_pathCache;
ProjectStorage &m_storage;
};
} // namespace QmlDesigner

View File

@@ -1095,8 +1095,8 @@ std::ostream &operator<<(std::ostream &out, Version version)
std::ostream &operator<<(std::ostream &out, const ExportedType &exportedType)
{
return out << "(\"" << exportedType.name << "\""
<< ", " << exportedType.version << ")";
return out << "(\"" << exportedType.name << "\"," << exportedType.moduleId << ", "
<< exportedType.version << ")";
}
std::ostream &operator<<(std::ostream &out, const NativeType &nativeType)
@@ -1116,10 +1116,9 @@ std::ostream &operator<<(std::ostream &out, const QualifiedImportedType &importe
std::ostream &operator<<(std::ostream &out, const Type &type)
{
using Utils::operator<<;
return out << "(moduleId: " << type.moduleId << ", typename: \"" << type.typeName
<< "\", prototype: " << type.prototype << ", " << type.accessSemantics
<< ", source: " << type.sourceId << ", exports: " << type.exportedTypes
<< ", properties: " << type.propertyDeclarations
return out << "( typename: \"" << type.typeName << "\", prototype: " << type.prototype << ", "
<< type.prototypeId << ", " << type.accessSemantics << ", source: " << type.sourceId
<< ", exports: " << type.exportedTypes << ", properties: " << type.propertyDeclarations
<< ", functions: " << type.functionDeclarations
<< ", signals: " << type.signalDeclarations << ")";
}
@@ -1127,9 +1126,10 @@ std::ostream &operator<<(std::ostream &out, const Type &type)
std::ostream &operator<<(std::ostream &out, const PropertyDeclaration &propertyDeclaration)
{
using Utils::operator<<;
return out << "(\"" << propertyDeclaration.name << "\", \"" << propertyDeclaration.typeName
<< "\", " << propertyDeclaration.traits << ", " << propertyDeclaration.typeId
<< ", \"" << propertyDeclaration.aliasPropertyName << "\")";
return out << "(\"" << propertyDeclaration.name << "\", " << propertyDeclaration.typeName
<< ", " << propertyDeclaration.typeId << ", " << propertyDeclaration.traits << ", "
<< propertyDeclaration.typeId << ", \"" << propertyDeclaration.aliasPropertyName
<< "\")";
}
std::ostream &operator<<(std::ostream &out, PropertyDeclarationTraits traits)
@@ -1186,11 +1186,6 @@ std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumer
<< enumerationDeclaration.enumeratorDeclarations << ")";
}
std::ostream &operator<<(std::ostream &out, const Module &module)
{
return out << "(" << module.name << ", " << module.sourceId << ")";
}
std::ostream &operator<<(std::ostream &out, const ImportKind &importKind)
{
return out << importKindToText(importKind);
@@ -1198,8 +1193,7 @@ std::ostream &operator<<(std::ostream &out, const ImportKind &importKind)
std::ostream &operator<<(std::ostream &out, const Import &import)
{
return out << "(" << import.name << ", " << import.version << ", " << import.sourceId << ", "
<< import.moduleId << ", " << import.kind << ")";
return out << "(" << import.moduleId << ", " << import.version << ", " << import.sourceId << ")";
}
} // namespace Storage

View File

@@ -260,8 +260,6 @@ class ParameterDeclaration;
class SignalDeclaration;
class EnumerationDeclaration;
class EnumeratorDeclaration;
class Module;
class ModuleDependency;
enum class ImportKind : char;
class Import;
enum class IsQualified : int;
@@ -281,8 +279,6 @@ std::ostream &operator<<(std::ostream &out, const ParameterDeclaration &paramete
std::ostream &operator<<(std::ostream &out, const SignalDeclaration &signalDeclaration);
std::ostream &operator<<(std::ostream &out, const EnumerationDeclaration &enumerationDeclaration);
std::ostream &operator<<(std::ostream &out, const EnumeratorDeclaration &enumeratorDeclaration);
std::ostream &operator<<(std::ostream &out, const Module &module);
std::ostream &operator<<(std::ostream &out, const ModuleDependency &module);
std::ostream &operator<<(std::ostream &out, const ImportKind &importKind);
std::ostream &operator<<(std::ostream &out, const Import &import);
std::ostream &operator<<(std::ostream &out, IsQualified isQualified);

File diff suppressed because it is too large Load Diff

View File

@@ -38,13 +38,14 @@ class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface
public:
MOCK_METHOD(void,
synchronize,
(QmlDesigner::Storage::Modules modules,
QmlDesigner::Storage::Imports imports,
(QmlDesigner::Storage::Imports imports,
QmlDesigner::Storage::Types types,
QmlDesigner::SourceIds sourceIds,
QmlDesigner::FileStatuses fileStatuses),
(override));
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (Utils::SmallStringView), (override));
MOCK_METHOD(QmlDesigner::FileStatus,
fetchFileStatus,
(QmlDesigner::SourceId sourceId),

View File

@@ -42,26 +42,25 @@ namespace {
namespace Storage = QmlDesigner::Storage;
using QmlDesigner::FileStatus;
using QmlDesigner::ModuleId;
using QmlDesigner::SourceId;
using QmlDesigner::Storage::TypeAccessSemantics;
namespace Storage = QmlDesigner::Storage;
using QmlDesigner::IdPaths;
using QmlDesigner::Storage::Version;
MATCHER_P5(IsStorageType,
moduleId,
MATCHER_P4(IsStorageType,
typeName,
prototype,
accessSemantics,
sourceId,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::Type{moduleId, typeName, prototype, accessSemantics, sourceId}))
+ PrintToString(Storage::Type{typeName, prototype, accessSemantics, sourceId}))
{
const Storage::Type &type = arg;
return type.moduleId == moduleId && type.typeName == typeName
&& type.accessSemantics == accessSemantics && type.sourceId == sourceId
&& Storage::ImportedTypeName{prototype} == type.prototype;
return type.typeName == typeName && type.accessSemantics == accessSemantics
&& type.sourceId == sourceId && Storage::ImportedTypeName{prototype} == type.prototype;
}
MATCHER_P3(IsPropertyDeclaration,
@@ -78,27 +77,20 @@ MATCHER_P3(IsPropertyDeclaration,
&& propertyDeclaration.traits == traits;
}
MATCHER_P3(IsExportedType,
MATCHER_P4(IsExportedType,
moduleId,
name,
majorVersion,
minorVersion,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::ExportedType{name,
+ PrintToString(Storage::ExportedType{moduleId,
name,
Storage::Version{majorVersion, minorVersion}}))
{
const Storage::ExportedType &type = arg;
return type.name == name && type.version == Storage::Version{majorVersion, minorVersion};
}
MATCHER_P2(IsModule,
name,
sourceId,
std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name, sourceId}))
{
const Storage::Module &module = arg;
return module.name == name && module.sourceId == sourceId;
return type.moduleId == moduleId && type.name == name
&& type.version == Storage::Version{majorVersion, minorVersion};
}
MATCHER_P3(IsFileStatus,
@@ -154,6 +146,8 @@ public:
.WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3)))
.WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 2}));
ON_CALL(projectStorageMock, moduleId(Eq("Example"))).WillByDefault(Return(exampleModuleId));
ON_CALL(projectStorageMock, moduleId(Eq("Qml"))).WillByDefault(Return(qmlModuleId));
firstType.prototype = Storage::ImportedType{"Object"};
secondType.prototype = Storage::ImportedType{"Object2"};
@@ -203,25 +197,26 @@ protected:
SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/example2.qmltypes");
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
QmlDesigner::ModuleId exampleModuleId{&qmlDirPathSourceId};
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml");
SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
Storage::Type objectType{exampleModuleId,
"QObject",
ModuleId qmlModuleId{storage.moduleId("Qml")};
ModuleId exampleModuleId{storage.moduleId("Example")};
Storage::Type objectType{"QObject",
Storage::NativeType{},
Storage::TypeAccessSemantics::Reference,
objectTypeSourceId,
{Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}};
{Storage::ExportedType{exampleModuleId, "Object"},
Storage::ExportedType{exampleModuleId, "Obj"}}};
QString qmlDocument1{"First{}"};
QString qmlDocument2{"Second{}"};
QString qmlDocument3{"Third{}"};
Storage::Type firstType;
Storage::Type secondType;
Storage::Type thirdType;
Storage::Import import1{"Qml", Storage::Version{2, 3}, qmlDocumentSourceId1};
Storage::Import import2{"Qml", Storage::Version{}, qmlDocumentSourceId2};
Storage::Import import3{"Qml", Storage::Version{2}, qmlDocumentSourceId3};
Storage::Import import1{qmlModuleId, Storage::Version{2, 3}, qmlDocumentSourceId1};
Storage::Import import2{qmlModuleId, Storage::Version{}, qmlDocumentSourceId2};
Storage::Import import3{qmlModuleId, Storage::Version{2}, qmlDocumentSourceId3};
};
TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent)
@@ -320,8 +315,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange)
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421}));
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
@@ -330,7 +324,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
{
auto qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
auto qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
Storage::Import import{"Qml", Storage::Version{2, 3}, qmltypesPathSourceId};
Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId};
QString qmltypes{"Module {\ndependencies: []}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
.WillByDefault(Return(qmltypes));
@@ -340,9 +334,9 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
imports.push_back(import);
});
EXPECT_CALL(projectStorageMock, moduleId(Eq("Example")));
EXPECT_CALL(projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
ElementsAre(import),
synchronize(ElementsAre(import),
ElementsAre(Eq(objectType)),
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
@@ -366,8 +360,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged)
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
EXPECT_CALL(projectStorageMock, synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
@@ -414,31 +407,28 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
EXPECT_CALL(projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
UnorderedElementsAre(import1, import2, import3),
EXPECT_CALL(
projectStorageMock,
synchronize(UnorderedElementsAre(import1, import2, import3),
UnorderedElementsAre(
AllOf(IsStorageType(exampleModuleId,
"First.qml",
AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 1, 0)))),
AllOf(IsStorageType(exampleModuleId,
"First.2.qml",
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))),
AllOf(IsStorageType("First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 2, 2)))),
AllOf(IsStorageType(exampleModuleId,
"Second.qml",
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2)))),
AllOf(IsStorageType("Second.qml",
Storage::ImportedType{"Object3"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId3),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("SecondType", 2, 2))))),
ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2))))),
UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
@@ -461,22 +451,20 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
EXPECT_CALL(
projectStorageMock,
synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)),
UnorderedElementsAre(import1, import2),
UnorderedElementsAre(AllOf(IsStorageType(exampleModuleId,
"First.qml",
synchronize(UnorderedElementsAre(import1, import2),
UnorderedElementsAre(
AllOf(IsStorageType("First.qml",
Storage::ImportedType{"Object"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId1),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 1, 0)))),
AllOf(IsStorageType(exampleModuleId,
"First.2.qml",
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0)))),
AllOf(IsStorageType("First.2.qml",
Storage::ImportedType{"Object2"},
TypeAccessSemantics::Reference,
qmlDocumentSourceId2),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType", 2, 2))))),
ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2))))),
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2),
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmlDocumentSourceId1, 22, 12),
@@ -485,31 +473,6 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate)
updater.update();
}
TEST_F(ProjectStorageUpdater, SynchronizeModules)
{
SourceId qmlDirPathSourceId2 = sourcePathCache.sourceId("/path2/qmldir");
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId2)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 22, 423}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId2)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 2, 421}));
QString qmldir2{"module Example2\n"};
ON_CALL(projectManagerMock, qtQmlDirs())
.WillByDefault(Return(QStringList{"/path/qmldir", "/path2/qmldir"}));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path2/qmldir")))).WillByDefault(Return(qmldir2));
EXPECT_CALL(projectStorageMock,
synchronize(UnorderedElementsAre(IsModule("Example", qmlDirPathSourceId),
IsModule("Example2", qmlDirPathSourceId2)),
_,
_,
_,
UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421),
IsFileStatus(qmltypesPathSourceId, 21, 421),
IsFileStatus(qmlDirPathSourceId2, 22, 423))));
updater.update();
}
TEST_F(ProjectStorageUpdater, UpdateQmldirDocuments)
{
QString qmldir{"module Example\nFirstType 1.1 First.qml\nFirstType 2.2 "

View File

@@ -129,7 +129,7 @@ protected:
QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
storage};
QmlDesigner::QmlDocumentParser parser{sourcePathCache};
QmlDesigner::QmlDocumentParser parser{sourcePathCache, storage};
Storage::Imports imports;
SourceId qmlFileSourceId{sourcePathCache.sourceId("path/to/qmlfile.qml")};
SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)};
@@ -146,6 +146,7 @@ TEST_F(QmlDocumentParser, Prototype)
TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype)
{
auto exampleModuleId = storage.moduleId("Example");
auto type = parser.parse("import Example as Example\n Example.Item{}",
imports,
qmlFileSourceId,
@@ -153,7 +154,7 @@ TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype)
ASSERT_THAT(type,
HasPrototype(Storage::QualifiedImportedType(
"Item", Storage::Import{"Example", Storage::Version{}, qmlFileSourceId})));
"Item", Storage::Import{exampleModuleId, Storage::Version{}, qmlFileSourceId})));
}
TEST_F(QmlDocumentParser, Properties)
@@ -171,7 +172,10 @@ TEST_F(QmlDocumentParser, Properties)
TEST_F(QmlDocumentParser, DISABLED_Imports)
{
ModuleId fooDirectoryModuleId{&sourcePathCache.sourceId("path/to/foo/.")};
ModuleId fooDirectoryModuleId = storage.moduleId("path/to/foo/.");
ModuleId qmlModuleId = storage.moduleId("QML");
ModuleId qtQmlModuleId = storage.moduleId("QtQml");
ModuleId qtQuickModuleId = storage.moduleId("QtQuick");
auto type = parser.parse("import QtQuick\n import \"../foo\"\nExample{}",
imports,
qmlFileSourceId,
@@ -179,11 +183,11 @@ TEST_F(QmlDocumentParser, DISABLED_Imports)
ASSERT_THAT(imports,
UnorderedElementsAre(
Storage::Import{Storage::Version{}, directoryModuleId, qmlFileSourceId},
Storage::Import{Storage::Version{}, fooDirectoryModuleId, qmlFileSourceId},
Storage::Import{"QML", Storage::Version{1, 0}, qmlFileSourceId},
Storage::Import{"QtQml", Storage::Version{6, 0}, qmlFileSourceId},
Storage::Import{"QtQuick", Storage::Version{}, qmlFileSourceId}));
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{qtQuickModuleId, Storage::Version{}, qmlFileSourceId}));
}
TEST_F(QmlDocumentParser, Functions)

View File

@@ -39,18 +39,16 @@ using QmlDesigner::ModuleId;
using QmlDesigner::SourceContextId;
using QmlDesigner::SourceId;
MATCHER_P4(IsImport,
name,
MATCHER_P3(IsImport,
moduleId,
version,
sourceId,
kind,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::Import{name, version, sourceId, kind}))
+ PrintToString(Storage::Import{moduleId, version, sourceId}))
{
const Storage::Import &import = arg;
return import.name == name && import.version == version && import.sourceId == sourceId
&& import.kind == kind;
return import.moduleId == moduleId && import.version == version && import.sourceId == sourceId;
}
MATCHER_P(HasPrototype, prototype, std::string(negation ? "isn't " : "is ") + PrintToString(prototype))
@@ -60,19 +58,17 @@ MATCHER_P(HasPrototype, prototype, std::string(negation ? "isn't " : "is ") + Pr
return Storage::ImportedTypeName{prototype} == type.prototype;
}
MATCHER_P5(IsType,
moduleId,
MATCHER_P4(IsType,
typeName,
prototype,
accessSemantics,
sourceId,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::Type{moduleId, typeName, prototype, accessSemantics, sourceId}))
+ PrintToString(Storage::Type{typeName, prototype, accessSemantics, sourceId}))
{
const Storage::Type &type = arg;
return type.moduleId == moduleId && type.typeName == typeName
&& type.prototype == Storage::ImportedTypeName{prototype}
return type.typeName == typeName && type.prototype == Storage::ImportedTypeName{prototype}
&& type.accessSemantics == accessSemantics && type.sourceId == sourceId;
}
@@ -173,13 +169,12 @@ protected:
QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
storage};
QmlDesigner::QmlTypesParser parser{sourcePathCache};
QmlDesigner::QmlTypesParser parser{sourcePathCache, storage};
Storage::Imports imports;
Storage::Types types;
SourceId qmltypesFileSourceId{sourcePathCache.sourceId("path/to/types.qmltypes")};
SourceContextId qmltypesFileSourceContextId{sourcePathCache.sourceContextId(qmltypesFileSourceId)};
SourceId directorySourceId{sourcePathCache.sourceId("path/to/.")};
ModuleId directoryModuleId{&directorySourceId};
ModuleId directoryModuleId{storage.moduleId("path/to/")};
};
TEST_F(QmlTypesParser, Imports)
@@ -191,27 +186,20 @@ TEST_F(QmlTypesParser, Imports)
parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId);
ASSERT_THAT(imports,
UnorderedElementsAre(IsImport("QtQuick",
Storage::Version{2, 15},
qmltypesFileSourceId,
Storage::ImportKind::QmlTypesDependency),
IsImport("QtQuick.Window",
ASSERT_THAT(
imports,
UnorderedElementsAre(
IsImport(storage.moduleId("QML"), Storage::Version{}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQml"), Storage::Version{}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQml-cppnative"), Storage::Version{}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQuick"), Storage::Version{2, 15}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQuick-cppnative"), Storage::Version{2, 15}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQuick.Window"), Storage::Version{2, 1}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtQuick.Window-cppnative"),
Storage::Version{2, 1},
qmltypesFileSourceId,
Storage::ImportKind::QmlTypesDependency),
IsImport("QML",
Storage::Version{},
qmltypesFileSourceId,
Storage::ImportKind::QmlTypesDependency),
IsImport("QtQml",
Storage::Version{},
qmltypesFileSourceId,
Storage::ImportKind::QmlTypesDependency),
IsImport("QtFoo",
Storage::Version{6},
qmltypesFileSourceId,
Storage::ImportKind::QmlTypesDependency)));
qmltypesFileSourceId),
IsImport(storage.moduleId("QtFoo"), Storage::Version{6}, qmltypesFileSourceId),
IsImport(storage.moduleId("QtFoo-cppnative"), Storage::Version{6}, qmltypesFileSourceId)));
}
TEST_F(QmlTypesParser, Types)
@@ -225,13 +213,11 @@ TEST_F(QmlTypesParser, Types)
parser.parse(source, imports, types, qmltypesFileSourceId, directoryModuleId);
ASSERT_THAT(types,
UnorderedElementsAre(IsType(directoryModuleId,
"QObject",
UnorderedElementsAre(IsType("QObject",
Storage::NativeType{},
Storage::TypeAccessSemantics::Reference,
qmltypesFileSourceId),
IsType(directoryModuleId,
"QQmlComponent",
IsType("QQmlComponent",
Storage::NativeType{"QObject"},
Storage::TypeAccessSemantics::Reference,
qmltypesFileSourceId)));