forked from qt-creator/qt-creator
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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user