forked from qt-creator/qt-creator
QmlDesigner: Alias support in the QmlDocumentParser
We have to adjust the storage to support indirect alias like: Item { property alias textSize: foo.text.size Text{ id: foo } } Task-number: QDS-7117 Change-Id: I0cf915ed710800dfa46ceff5d823e48ef45ec906 Change-Id: I11df6077ebbda208114b5e6f9c4eece611740096 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include "qmldocumentparser.h"
|
||||
|
||||
#include "projectstorage.h"
|
||||
#include "projectstorageexceptions.h"
|
||||
#include "sourcepathcache.h"
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
@@ -161,16 +162,35 @@ Storage::ImportedTypeName createImportedTypeName(const QStringView rawtypeName,
|
||||
}
|
||||
|
||||
void addPropertyDeclarations(Storage::Type &type,
|
||||
const QmlDom::QmlObject &rootObject,
|
||||
const QualifiedImports &qualifiedImports)
|
||||
QmlDom::QmlObject &rootObject,
|
||||
const QualifiedImports &qualifiedImports,
|
||||
QmlDom::DomItem &fileItem)
|
||||
{
|
||||
for (const QmlDom::PropertyDefinition &propertyDeclaration : rootObject.propertyDefs()) {
|
||||
if (propertyDeclaration.isAlias()) {
|
||||
auto rootObjectItem = fileItem.copy(&rootObject);
|
||||
auto property = rootObjectItem.bindings()
|
||||
.key(propertyDeclaration.name)
|
||||
.index(0)
|
||||
.field(QmlDom::Fields::value);
|
||||
auto resolvedAlias = rootObject.resolveAlias(rootObjectItem,
|
||||
property.ownerAs<QmlDom::ScriptExpression>());
|
||||
if (resolvedAlias.valid()) {
|
||||
type.propertyDeclarations.emplace_back(Utils::SmallString{propertyDeclaration.name},
|
||||
createImportedTypeName(resolvedAlias.typeName,
|
||||
qualifiedImports),
|
||||
Storage::PropertyDeclarationTraits::None,
|
||||
Utils::SmallString{
|
||||
resolvedAlias.accessedPath.join('.')});
|
||||
}
|
||||
} else {
|
||||
type.propertyDeclarations.emplace_back(Utils::SmallString{propertyDeclaration.name},
|
||||
createImportedTypeName(propertyDeclaration.typeName,
|
||||
qualifiedImports),
|
||||
Storage::PropertyDeclarationTraits::None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParameterDeclaration(Storage::ParameterDeclarations ¶meterDeclarations,
|
||||
const QList<QmlDom::MethodParameter> ¶meters)
|
||||
@@ -256,12 +276,12 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
|
||||
return type;
|
||||
|
||||
const auto &component = components.first();
|
||||
const auto &objects = component.objects();
|
||||
auto objects = component.objects();
|
||||
|
||||
if (objects.empty())
|
||||
return type;
|
||||
|
||||
const QmlDom::QmlObject &qmlObject = objects.front();
|
||||
QmlDom::QmlObject &qmlObject = objects.front();
|
||||
|
||||
const auto qmlImports = qmlFile->imports();
|
||||
|
||||
@@ -274,7 +294,7 @@ Storage::Type QmlDocumentParser::parse(const QString &sourceContent,
|
||||
|
||||
addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage);
|
||||
|
||||
addPropertyDeclarations(type, qmlObject, qualifiedImports);
|
||||
addPropertyDeclarations(type, qmlObject, qualifiedImports, file);
|
||||
addFunctionAndSignalDeclarations(type, qmlObject);
|
||||
addEnumeraton(type, component);
|
||||
|
||||
|
@@ -59,6 +59,22 @@ MATCHER_P3(IsPropertyDeclaration,
|
||||
&& propertyDeclaration.traits == traits;
|
||||
}
|
||||
|
||||
MATCHER_P4(IsAliasPropertyDeclaration,
|
||||
name,
|
||||
typeName,
|
||||
traits,
|
||||
aliasPropertyName,
|
||||
std::string(negation ? "isn't " : "is ")
|
||||
+ PrintToString(Storage::PropertyDeclaration{name, typeName, traits, aliasPropertyName}))
|
||||
{
|
||||
const Storage::PropertyDeclaration &propertyDeclaration = arg;
|
||||
|
||||
return propertyDeclaration.name == name
|
||||
&& Storage::ImportedTypeName{typeName} == propertyDeclaration.typeName
|
||||
&& propertyDeclaration.traits == traits
|
||||
&& propertyDeclaration.aliasPropertyName == aliasPropertyName;
|
||||
}
|
||||
|
||||
MATCHER_P2(IsFunctionDeclaration,
|
||||
name,
|
||||
returnTypeName,
|
||||
@@ -367,4 +383,75 @@ TEST_F(QmlDocumentParser, DISABLED_DuplicateImportsAreRemoved)
|
||||
Storage::Import{qtQuickModuleId, Storage::Version{}, qmlFileSourceId}));
|
||||
}
|
||||
|
||||
TEST_F(QmlDocumentParser, AliasItemProperties)
|
||||
{
|
||||
auto type = parser.parse(R"(Example{
|
||||
property alias delegate: foo
|
||||
Item {
|
||||
id: foo
|
||||
}
|
||||
})",
|
||||
imports,
|
||||
qmlFileSourceId,
|
||||
directoryPath);
|
||||
|
||||
ASSERT_THAT(type.propertyDeclarations,
|
||||
UnorderedElementsAre(IsPropertyDeclaration("delegate",
|
||||
Storage::ImportedType{"Item"},
|
||||
Storage::PropertyDeclarationTraits::None)));
|
||||
}
|
||||
|
||||
TEST_F(QmlDocumentParser, AliasProperties)
|
||||
{
|
||||
auto type = parser.parse(R"(Example{
|
||||
property alias text: foo.text2
|
||||
Item {
|
||||
id: foo
|
||||
}
|
||||
})",
|
||||
imports,
|
||||
qmlFileSourceId,
|
||||
directoryPath);
|
||||
|
||||
ASSERT_THAT(type.propertyDeclarations,
|
||||
UnorderedElementsAre(IsAliasPropertyDeclaration("text",
|
||||
Storage::ImportedType{"Item"},
|
||||
Storage::PropertyDeclarationTraits::None,
|
||||
"text2")));
|
||||
}
|
||||
|
||||
TEST_F(QmlDocumentParser, IndirectAliasProperties)
|
||||
{
|
||||
auto type = parser.parse(R"(Example{
|
||||
property alias textSize: foo.text.size
|
||||
Item {
|
||||
id: foo
|
||||
}
|
||||
})",
|
||||
imports,
|
||||
qmlFileSourceId,
|
||||
directoryPath);
|
||||
|
||||
ASSERT_THAT(type.propertyDeclarations,
|
||||
UnorderedElementsAre(IsAliasPropertyDeclaration("textSize",
|
||||
Storage::ImportedType{"Item"},
|
||||
Storage::PropertyDeclarationTraits::None,
|
||||
"text.size")));
|
||||
}
|
||||
|
||||
TEST_F(QmlDocumentParser, InvalidAliasPropertiesAreSkipped)
|
||||
{
|
||||
auto type = parser.parse(R"(Example{
|
||||
property alias textSize: foo2.text.size
|
||||
Item {
|
||||
id: foo
|
||||
}
|
||||
})",
|
||||
imports,
|
||||
qmlFileSourceId,
|
||||
directoryPath);
|
||||
|
||||
ASSERT_THAT(type.propertyDeclarations, IsEmpty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user