QmlDesigner: Add imports for qml document parser

Task-number: QDS-5174
Change-Id: I78b7b31108b498035eccb8385ffab621c727cd89
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2021-10-21 11:55:07 +02:00
parent 607f70f0f9
commit 9d24d886e2
3 changed files with 38 additions and 40 deletions

View File

@@ -32,6 +32,7 @@
#include <qmldom/qqmldomtop_p.h>
#include <filesystem>
#include <QDateTime>
namespace QmlDesigner {
@@ -53,30 +54,28 @@ Storage::Version convertVersion(QmlDom::Version version)
Utils::PathString convertUri(const QString &uri)
{
Utils::PathString path{QStringView{uri.begin() + 7, uri.end()}};
if (path.endsWith("/."))
return path;
if (path.endsWith("/")) {
path += ".";
return path;
}
QStringView localPath{uri.begin() + 7, uri.end()};
path += "/.";
return path;
std::filesystem::path path{
std::u16string_view{localPath.utf16(), static_cast<std::size_t>(localPath.size())}};
auto x = std::filesystem::weakly_canonical(path);
return Utils::PathString{x.generic_string()};
}
void addImports(Storage::Imports &imports,
const QList<QmlDom::Import> &qmlImports,
SourceId sourceId,
SourceContextId sourceContextId,
QmlDocumentParser::PathCache &pathCache,
const QString &directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
for (const QmlDom::Import &qmlImport : qmlImports) {
if (qmlImport.uri == u"file://.") {
auto moduleId = storage.moduleId(pathCache.sourceContextPath(sourceContextId));
auto moduleId = storage.moduleId(Utils::PathString{directoryPath});
imports.emplace_back(moduleId, Storage::Version{}, sourceId);
} else if (qmlImport.uri.startsWith(u"file://")) {
auto x = convertUri(qmlImport.uri);
auto moduleId = storage.moduleId(convertUri(qmlImport.uri));
imports.emplace_back(moduleId, Storage::Version{}, sourceId);
} else {
@@ -144,7 +143,7 @@ void addEnumeraton(Storage::Type &type, const QmlDom::Component &component)
Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
Storage::Imports &imports,
SourceId sourceId,
SourceContextId sourceContextId)
const QString &directoryPath)
{
Storage::Type type;
@@ -155,9 +154,11 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
QmlDom::DomItem items;
QString filePath{directoryPath + "/foo.qml"};
environment.loadFile(
{},
{},
filePath,
filePath,
sourceContent,
QDateTime{},
[&](QmlDom::Path, const QmlDom::DomItem &, const QmlDom::DomItem &newItems) {
@@ -185,7 +186,7 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
type.prototype = Storage::ImportedType{Utils::SmallString{qmlObject.name()}};
addImports(imports, qmlFile->imports(), sourceId, sourceContextId, m_pathCache, m_storage);
addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage);
addPropertyDeclarations(type, qmlObject);
addFunctionAndSignalDeclarations(type, qmlObject);

View File

@@ -46,18 +46,16 @@ public:
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
QmlDocumentParser(PathCache &pathCache, ProjectStorage &storage)
: m_pathCache{pathCache}
, m_storage{storage}
QmlDocumentParser(ProjectStorage &storage)
: m_storage{storage}
{}
virtual Storage::Type parse(const QString &sourceContent,
Storage::Imports &imports,
SourceId sourceId,
SourceContextId sourceContextId);
Storage::Type parse(const QString &sourceContent,
Storage::Imports &imports,
SourceId sourceId,
const QString &directoryPath);
private:
PathCache &m_pathCache;
ProjectStorage &m_storage;
};
} // namespace QmlDesigner

View File

@@ -129,17 +129,17 @@ protected:
QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
storage};
QmlDesigner::QmlDocumentParser parser{sourcePathCache, storage};
QmlDesigner::QmlDocumentParser parser{storage};
Storage::Imports imports;
SourceId qmlFileSourceId{sourcePathCache.sourceId("path/to/qmlfile.qml")};
SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)};
SourceId directorySourceId{sourcePathCache.sourceId("path/to/.")};
ModuleId directoryModuleId{&directorySourceId};
QString directoryPath{"/path/to"};
ModuleId directoryModuleId{storage.moduleId("/path/to")};
};
TEST_F(QmlDocumentParser, Prototype)
{
auto type = parser.parse("Example{}", imports, qmlFileSourceId, qmlFileSourceContextId);
auto type = parser.parse("Example{}", imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example")));
}
@@ -150,7 +150,7 @@ TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype)
auto type = parser.parse("import Example as Example\n Example.Item{}",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
directoryPath);
ASSERT_THAT(type,
HasPrototype(Storage::QualifiedImportedType(
@@ -159,10 +159,7 @@ TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype)
TEST_F(QmlDocumentParser, Properties)
{
auto type = parser.parse("Example{\n property int foo\n}",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
auto type = parser.parse("Example{\n property int foo\n}", imports, qmlFileSourceId, directoryPath);
ASSERT_THAT(type.propertyDeclarations,
UnorderedElementsAre(IsPropertyDeclaration("foo",
@@ -170,16 +167,18 @@ TEST_F(QmlDocumentParser, Properties)
Storage::PropertyDeclarationTraits::None)));
}
TEST_F(QmlDocumentParser, DISABLED_Imports)
TEST_F(QmlDocumentParser, Imports)
{
ModuleId fooDirectoryModuleId = storage.moduleId("path/to/foo/.");
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("import QtQuick\n import \"../foo\"\nExample{}",
auto type = parser.parse(R"(import QtQuick
import "../foo"
Example{})",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
directoryPath);
ASSERT_THAT(imports,
UnorderedElementsAre(
@@ -196,7 +195,7 @@ TEST_F(QmlDocumentParser, Functions)
"Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
directoryPath);
ASSERT_THAT(type.functionDeclarations,
UnorderedElementsAre(AllOf(IsFunctionDeclaration("otherFunction", ""),
@@ -212,7 +211,7 @@ TEST_F(QmlDocumentParser, Signals)
auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
directoryPath);
ASSERT_THAT(type.signalDeclarations,
UnorderedElementsAre(AllOf(IsSignalDeclaration("someSignal"),
@@ -229,7 +228,7 @@ TEST_F(QmlDocumentParser, Enumeration)
"State{On,Off}\n}",
imports,
qmlFileSourceId,
qmlFileSourceContextId);
directoryPath);
ASSERT_THAT(type.enumerationDeclarations,
UnorderedElementsAre(