forked from qt-creator/qt-creator
QmlDesigner: Add support for implicit import "."
Task-number: QDS-6780 Change-Id: Idd8b58a04203f56296e72dd3bbb73f720eb02277 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -214,6 +214,8 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
|
|||||||
for (const QString &qmldirPath : qmlDirs) {
|
for (const QString &qmldirPath : qmlDirs) {
|
||||||
SourcePath qmldirSourcePath{qmldirPath};
|
SourcePath qmldirSourcePath{qmldirPath};
|
||||||
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
|
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
|
||||||
|
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
|
||||||
|
Utils::PathString directoryPath = m_pathCache.sourceContextPath(directoryId);
|
||||||
|
|
||||||
auto state = fileState(qmlDirSourceId,
|
auto state = fileState(qmlDirSourceId,
|
||||||
package.fileStatuses,
|
package.fileStatuses,
|
||||||
@@ -226,11 +228,11 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
|
|||||||
|
|
||||||
package.updatedSourceIds.push_back(qmlDirSourceId);
|
package.updatedSourceIds.push_back(qmlDirSourceId);
|
||||||
|
|
||||||
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
|
|
||||||
|
|
||||||
Utils::PathString moduleName{parser.typeNamespace()};
|
Utils::PathString moduleName{parser.typeNamespace()};
|
||||||
ModuleId moduleId = m_projectStorage.moduleId(moduleName);
|
ModuleId moduleId = m_projectStorage.moduleId(moduleName);
|
||||||
ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative");
|
ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative");
|
||||||
|
ModuleId pathModuleId = m_projectStorage.moduleId(directoryPath);
|
||||||
|
|
||||||
auto imports = filterMultipleEntries(parser.imports());
|
auto imports = filterMultipleEntries(parser.imports());
|
||||||
|
|
||||||
@@ -252,7 +254,7 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
|
|||||||
filterMultipleEntries(parser.dependencies()),
|
filterMultipleEntries(parser.dependencies()),
|
||||||
imports,
|
imports,
|
||||||
qmlDirSourceId,
|
qmlDirSourceId,
|
||||||
directoryId,
|
directoryPath,
|
||||||
cppModuleId,
|
cppModuleId,
|
||||||
package,
|
package,
|
||||||
notUpdatedFileStatusSourceIds,
|
notUpdatedFileStatusSourceIds,
|
||||||
@@ -262,6 +264,7 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
|
|||||||
qmlDirSourceId,
|
qmlDirSourceId,
|
||||||
directoryId,
|
directoryId,
|
||||||
moduleId,
|
moduleId,
|
||||||
|
pathModuleId,
|
||||||
package,
|
package,
|
||||||
notUpdatedFileStatusSourceIds);
|
notUpdatedFileStatusSourceIds);
|
||||||
package.updatedProjectSourceIds.push_back(qmlDirSourceId);
|
package.updatedProjectSourceIds.push_back(qmlDirSourceId);
|
||||||
@@ -270,7 +273,7 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs,
|
|||||||
case FileState::NotChanged: {
|
case FileState::NotChanged: {
|
||||||
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
||||||
parseTypeInfos(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds);
|
parseTypeInfos(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds);
|
||||||
parseQmlComponents(qmlProjectDatas, package, notUpdatedFileStatusSourceIds);
|
parseQmlComponents(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, directoryPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FileState::NotExists: {
|
case FileState::NotExists: {
|
||||||
@@ -292,17 +295,16 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
|
|||||||
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 ¬UpdatedFileStatusSourceIds,
|
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||||
SourceIds ¬UpdatedSourceIds)
|
SourceIds ¬UpdatedSourceIds)
|
||||||
{
|
{
|
||||||
const Utils::PathString directory{m_pathCache.sourceContextPath(directoryId)};
|
|
||||||
|
|
||||||
for (const QString &typeInfo : typeInfos) {
|
for (const QString &typeInfo : typeInfos) {
|
||||||
Utils::PathString qmltypesPath = Utils::PathString::join(
|
Utils::PathString qmltypesPath = Utils::PathString::join(
|
||||||
{directory, "/", Utils::SmallString{typeInfo}});
|
{directoryPath, "/", Utils::SmallString{typeInfo}});
|
||||||
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmltypesPath});
|
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmltypesPath});
|
||||||
|
|
||||||
addDependencies(package.moduleDependencies,
|
addDependencies(package.moduleDependencies,
|
||||||
@@ -373,7 +375,7 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::ProjectData &projectDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFilePath,
|
void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFilePath,
|
||||||
Utils::SmallStringView directory,
|
Utils::SmallStringView directoryPath,
|
||||||
Storage::ExportedTypes exportedTypes,
|
Storage::ExportedTypes exportedTypes,
|
||||||
ModuleId moduleId,
|
ModuleId moduleId,
|
||||||
SourceId qmldirSourceId,
|
SourceId qmldirSourceId,
|
||||||
@@ -383,7 +385,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
|
|||||||
if (std::find(relativeFilePath.begin(), relativeFilePath.end(), '+') != relativeFilePath.end())
|
if (std::find(relativeFilePath.begin(), relativeFilePath.end(), '+') != relativeFilePath.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Utils::PathString qmlFilePath = Utils::PathString::join({directory, "/", relativeFilePath});
|
Utils::PathString qmlFilePath = Utils::PathString::join({directoryPath, "/", relativeFilePath});
|
||||||
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmlFilePath});
|
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmlFilePath});
|
||||||
|
|
||||||
Storage::Type type;
|
Storage::Type type;
|
||||||
@@ -400,7 +402,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
|
|||||||
throw CannotParseQmlDocumentFile{};
|
throw CannotParseQmlDocumentFile{};
|
||||||
case FileState::Changed:
|
case FileState::Changed:
|
||||||
const auto content = m_fileSystem.contentAsQString(QString{qmlFilePath});
|
const auto content = m_fileSystem.contentAsQString(QString{qmlFilePath});
|
||||||
type = m_qmlDocumentParser.parse(content, package.imports, sourceId);
|
type = m_qmlDocumentParser.parse(content, package.imports, sourceId, directoryPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +420,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
|
|||||||
|
|
||||||
void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView fileName,
|
void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView fileName,
|
||||||
Utils::SmallStringView filePath,
|
Utils::SmallStringView filePath,
|
||||||
|
Utils::SmallStringView directoryPath,
|
||||||
SourceId sourceId,
|
SourceId sourceId,
|
||||||
Storage::SynchronizationPackage &package,
|
Storage::SynchronizationPackage &package,
|
||||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||||
@@ -434,7 +437,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView fileName,
|
|||||||
SourcePath sourcePath{filePath};
|
SourcePath sourcePath{filePath};
|
||||||
|
|
||||||
const auto content = m_fileSystem.contentAsQString(QString{filePath});
|
const auto content = m_fileSystem.contentAsQString(QString{filePath});
|
||||||
auto type = m_qmlDocumentParser.parse(content, package.imports, sourceId);
|
auto type = m_qmlDocumentParser.parse(content, package.imports, sourceId, directoryPath);
|
||||||
|
|
||||||
type.typeName = fileName;
|
type.typeName = fileName;
|
||||||
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
||||||
@@ -483,14 +486,28 @@ void partitionForTheSameFileName(const ComponentReferences &components, Callback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::ExportedTypes filterExportedTypes(ComponentReferencesRange components, ModuleId moduleId)
|
Storage::ExportedTypes createExportedTypes(ComponentReferencesRange components,
|
||||||
|
ModuleId moduleId,
|
||||||
|
Utils::SmallStringView fileName,
|
||||||
|
ModuleId pathModuleId)
|
||||||
{
|
{
|
||||||
return Utils::transform<Storage::ExportedTypes>(components, [&](ComponentReference component) {
|
Storage::ExportedTypes exportedTypes;
|
||||||
return Storage::ExportedType{moduleId,
|
exportedTypes.reserve(components.size() + 1);
|
||||||
Utils::SmallString{component.get().typeName},
|
|
||||||
Storage::Version{component.get().majorVersion,
|
for (ComponentReference component : components) {
|
||||||
component.get().minorVersion}};
|
exportedTypes.emplace_back(moduleId,
|
||||||
});
|
Utils::SmallString{component.get().typeName},
|
||||||
|
Storage::Version{component.get().majorVersion,
|
||||||
|
component.get().minorVersion});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto foundDot = std::find(fileName.begin(), fileName.end(), '.');
|
||||||
|
|
||||||
|
exportedTypes.emplace_back(pathModuleId,
|
||||||
|
Utils::SmallStringView{fileName.begin(), foundDot},
|
||||||
|
Storage::Version{});
|
||||||
|
|
||||||
|
return exportedTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -499,6 +516,7 @@ void ProjectStorageUpdater::parseQmlComponents(ComponentReferences components,
|
|||||||
SourceId qmldirSourceId,
|
SourceId qmldirSourceId,
|
||||||
SourceContextId directoryId,
|
SourceContextId directoryId,
|
||||||
ModuleId moduleId,
|
ModuleId moduleId,
|
||||||
|
ModuleId pathModuleId,
|
||||||
Storage::SynchronizationPackage &package,
|
Storage::SynchronizationPackage &package,
|
||||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||||
{
|
{
|
||||||
@@ -513,13 +531,14 @@ void ProjectStorageUpdater::parseQmlComponents(ComponentReferences components,
|
|||||||
second.get().minorVersion);
|
second.get().minorVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto directory = m_pathCache.sourceContextPath(directoryId);
|
auto directoryPath = m_pathCache.sourceContextPath(directoryId);
|
||||||
|
|
||||||
auto callback = [&](ComponentReferencesRange componentsWithSameFileName) {
|
auto callback = [&](ComponentReferencesRange componentsWithSameFileName) {
|
||||||
const auto &firstComponent = *componentsWithSameFileName.begin();
|
const auto &firstComponent = *componentsWithSameFileName.begin();
|
||||||
parseQmlComponent(Utils::SmallString{firstComponent.get().fileName},
|
const Utils::SmallString fileName{firstComponent.get().fileName};
|
||||||
directory,
|
parseQmlComponent(fileName,
|
||||||
filterExportedTypes(componentsWithSameFileName, moduleId),
|
directoryPath,
|
||||||
|
createExportedTypes(componentsWithSameFileName, moduleId, fileName, pathModuleId),
|
||||||
moduleId,
|
moduleId,
|
||||||
qmldirSourceId,
|
qmldirSourceId,
|
||||||
package,
|
package,
|
||||||
@@ -531,7 +550,8 @@ void ProjectStorageUpdater::parseQmlComponents(ComponentReferences components,
|
|||||||
|
|
||||||
void ProjectStorageUpdater::parseQmlComponents(const Storage::ProjectDatas &projectDatas,
|
void ProjectStorageUpdater::parseQmlComponents(const Storage::ProjectDatas &projectDatas,
|
||||||
Storage::SynchronizationPackage &package,
|
Storage::SynchronizationPackage &package,
|
||||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||||
|
Utils::SmallStringView directoryPath)
|
||||||
{
|
{
|
||||||
for (const Storage::ProjectData &projectData : projectDatas) {
|
for (const Storage::ProjectData &projectData : projectDatas) {
|
||||||
if (projectData.fileType != Storage::FileType::QmlDocument)
|
if (projectData.fileType != Storage::FileType::QmlDocument)
|
||||||
@@ -541,6 +561,7 @@ void ProjectStorageUpdater::parseQmlComponents(const Storage::ProjectDatas &proj
|
|||||||
|
|
||||||
parseQmlComponent(qmlDocumentPath.name(),
|
parseQmlComponent(qmlDocumentPath.name(),
|
||||||
qmlDocumentPath,
|
qmlDocumentPath,
|
||||||
|
directoryPath,
|
||||||
projectData.sourceId,
|
projectData.sourceId,
|
||||||
package,
|
package,
|
||||||
notUpdatedFileStatusSourceIds);
|
notUpdatedFileStatusSourceIds);
|
||||||
|
@@ -1022,31 +1022,31 @@ TEST_F(ProjectStorageUpdater, DontSynchronizeSelectors)
|
|||||||
|
|
||||||
TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithRelativeFilePath)
|
TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithRelativeFilePath)
|
||||||
{
|
{
|
||||||
SourceId qmlDocumentSourceId = sourcePathCache.sourceId("/path/qml/First.qml");
|
SourceId qmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml");
|
||||||
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId)))
|
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId)))
|
||||||
.WillByDefault(Return(FileStatus{qmlDocumentSourceId, 22, 12}));
|
.WillByDefault(Return(FileStatus{qmlDocumentSourceId, 22, 12}));
|
||||||
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qml/First.qml"))))
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
|
||||||
.WillByDefault(Return(qmlDocument1));
|
.WillByDefault(Return(qmlDocument1));
|
||||||
QString qmldir{R"(module Example
|
QString qmldir{R"(module Example
|
||||||
FirstType 1.0 qml/First.qml
|
FirstType 1.0 First.qml
|
||||||
FirstType2 1.0 qml/First.qml)"};
|
FirstType2 1.0 First.qml)"};
|
||||||
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
|
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
|
||||||
|
|
||||||
EXPECT_CALL(projectStorageMock,
|
EXPECT_CALL(projectStorageMock,
|
||||||
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,
|
||||||
qmlDocumentSourceId,
|
qmlDocumentSourceId,
|
||||||
Storage::ChangeLevel::Full),
|
Storage::ChangeLevel::Full),
|
||||||
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)))))),
|
IsExportedType(pathModuleId, "First", -1, -1)))))),
|
||||||
Field(&SynchronizationPackage::updatedSourceIds,
|
Field(&SynchronizationPackage::updatedSourceIds,
|
||||||
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)),
|
UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)),
|
||||||
Field(&SynchronizationPackage::updatedFileStatusSourceIds,
|
Field(&SynchronizationPackage::updatedFileStatusSourceIds,
|
||||||
|
Reference in New Issue
Block a user