QmlProject: port changes from QtForMcus

Task-number: QTCREATORBUG-26041
Change-Id: I5068381fb2c4c901d8621e0b8358db77d2cb0b21
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Christiaan Janssen
2021-09-27 15:28:36 +02:00
parent 3ad9c64977
commit 525039daeb
10 changed files with 424 additions and 343 deletions

View File

@@ -25,9 +25,15 @@
#include "qmljssimplereader.h" #include "qmljssimplereader.h"
#include "parser/qmljsparser_p.h" #ifdef QT_CREATOR
#include "parser/qmljslexer_p.h"
#include "parser/qmljsengine_p.h" #include "parser/qmljsengine_p.h"
#include "parser/qmljslexer_p.h"
#include "parser/qmljsparser_p.h"
#else
#include "parser/qqmljsengine_p.h"
#include "parser/qqmljslexer_p.h"
#include "qqmljsparser_p.h"
#endif
#include "qmljsutils.h" #include "qmljsutils.h"
@@ -37,308 +43,331 @@
static Q_LOGGING_CATEGORY(simpleReaderLog, "qtc.qmljs.simpleReader", QtWarningMsg) static Q_LOGGING_CATEGORY(simpleReaderLog, "qtc.qmljs.simpleReader", QtWarningMsg)
namespace QmlJS{ namespace QmlJS
QVariant SimpleReaderNode::property(const QString &name) const
{ {
return m_properties.value(name); #ifdef QT_CREATOR
} using UiQualifiedId = QmlJS::AST::UiQualifiedId;
#else
using UiQualifiedId = QQmlJS::AST::UiQualifiedId;
#endif
QStringList SimpleReaderNode::propertyNames() const static SourceLocation toSourceLocation(SourceLocation first, SourceLocation last)
{ {
return m_properties.keys(); first.length = last.end() - first.begin();
} return first;
SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const
{
return m_properties;
}
bool SimpleReaderNode::isRoot() const
{
return m_parentNode.isNull();
}
bool SimpleReaderNode::isValid() const
{
return !m_name.isEmpty();
}
SimpleReaderNode::Ptr SimpleReaderNode::invalidNode()
{
return Ptr(new SimpleReaderNode);
}
SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const
{
return m_parentNode;
}
QString SimpleReaderNode::name() const
{
return m_name;
}
SimpleReaderNode::SimpleReaderNode()
{
}
SimpleReaderNode::SimpleReaderNode(const QString &name, WeakPtr parent)
: m_name(name), m_parentNode(parent)
{
}
SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name, WeakPtr parent)
{
Ptr newNode(new SimpleReaderNode(name, parent));
newNode->m_weakThis = newNode;
if (parent)
parent.toStrongRef().data()->m_children.append(newNode);
return newNode;
}
const SimpleReaderNode::List SimpleReaderNode::children() const
{
return m_children;
}
void SimpleReaderNode::setProperty(const QString &name, const QVariant &value)
{
m_properties.insert(name, value);
}
SimpleAbstractStreamReader::SimpleAbstractStreamReader()
{
}
bool SimpleAbstractStreamReader::readFile(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray source = file.readAll();
file.close();
return readFromSource(QString::fromLocal8Bit(source));
} }
addError(tr("Cannot find file %1.").arg(fileName));
return false;
}
bool SimpleAbstractStreamReader::readFromSource(const QString &source) static SourceLocation toSourceLocation(UiQualifiedId * qualifiedId)
{ {
m_errors.clear(); SourceLocation first = qualifiedId->firstSourceLocation();
m_currentSourceLocation = SourceLocation(); SourceLocation last;
for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
m_source = source; if (iter->lastSourceLocation().isValid())
last = iter->lastSourceLocation();
Engine engine; }
Lexer lexer(&engine); return toSourceLocation(first, last);
Parser parser(&engine);
lexer.setCode(source, /*line = */ 1, /*qmlMode = */true);
if (!parser.parse()) {
QString errorMessage = QString::fromLatin1("%1:%2: %3").arg(
QString::number(parser.errorLineNumber()),
QString::number(parser.errorColumnNumber()),
parser.errorMessage());
addError(errorMessage);
return false;
} }
return readDocument(parser.ast());
}
QStringList SimpleAbstractStreamReader::errors() const SimpleReaderNode::Property SimpleReaderNode::property(const QString &name) const
{ {
return m_errors; return m_properties.value(name);
} }
void SimpleAbstractStreamReader::addError(const QString &error, const SourceLocation &sourceLocation) QStringList SimpleReaderNode::propertyNames() const { return m_properties.keys(); }
{
m_errors << QString::fromLatin1("%1:%2: %3\n").arg(
QString::number(sourceLocation.startLine),
QString::number(sourceLocation.startColumn),
error);
}
SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const { return m_properties; }
{
return m_currentSourceLocation;
}
bool SimpleAbstractStreamReader::readDocument(AST::UiProgram *ast) bool SimpleReaderNode::isRoot() const { return m_parentNode.isNull(); }
{
if (!ast) { bool SimpleReaderNode::isValid() const { return !m_name.isEmpty(); }
addError(tr("Could not parse document."));
SimpleReaderNode::Ptr SimpleReaderNode::invalidNode() { return Ptr(new SimpleReaderNode); }
SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const { return m_parentNode; }
QString SimpleReaderNode::name() const { return m_name; }
SourceLocation SimpleReaderNode::nameLocation() const { return m_nameLocation; }
SimpleReaderNode::SimpleReaderNode() {}
SimpleReaderNode::SimpleReaderNode(const QString &name,
const SourceLocation &nameLocation,
WeakPtr parent)
: m_name(name)
, m_nameLocation(nameLocation)
, m_parentNode(parent)
{}
SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name,
const SourceLocation &nameLocation,
WeakPtr parent)
{
Ptr newNode(new SimpleReaderNode(name, nameLocation, parent));
newNode->m_weakThis = newNode;
if (parent)
parent.toStrongRef().data()->m_children.append(newNode);
return newNode;
}
const SimpleReaderNode::List SimpleReaderNode::children() const { return m_children; }
void SimpleReaderNode::setProperty(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
{
m_properties.insert(name, {value, nameLocation, valueLocation});
}
SimpleAbstractStreamReader::SimpleAbstractStreamReader() {}
SimpleAbstractStreamReader::~SimpleAbstractStreamReader() {}
bool SimpleAbstractStreamReader::readFile(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray source = file.readAll();
file.close();
return readFromSource(QString::fromLocal8Bit(source));
}
addError(tr("Cannot find file %1.").arg(fileName));
return false; return false;
} }
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(ast->members->member); bool SimpleAbstractStreamReader::readFromSource(const QString &source)
if (!uiObjectDefinition) { {
addError(tr("Expected document to contain a single object definition.")); m_errors.clear();
return false; m_currentSourceLocation = SourceLocation();
}
readChild(uiObjectDefinition);
m_source.clear(); m_source = source;
return errors().isEmpty(); Engine engine;
} Lexer lexer(&engine);
Parser parser(&engine);
void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition *uiObjectDefinition) lexer.setCode(source, /*line = */ 1, /*qmlMode = */ true);
{
Q_ASSERT(uiObjectDefinition);
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) { if (!parser.parse()) {
AST::UiObjectMember *member = it->member; QString errorMessage = QString::fromLatin1("%1:%2: %3")
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(member); .arg(QString::number(parser.errorLineNumber()),
if (uiObjectDefinition) QString::number(parser.errorColumnNumber()),
readChild(uiObjectDefinition); parser.errorMessage());
} addError(errorMessage);
} return false;
}
void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition *uiObjectDefinition) return readDocument(parser.ast());
{
Q_ASSERT(uiObjectDefinition);
setSourceLocation(uiObjectDefinition->firstSourceLocation());
elementStart(toString(uiObjectDefinition->qualifiedTypeNameId));
readProperties(uiObjectDefinition);
readChildren(uiObjectDefinition);
elementEnd();
}
void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition *uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(member);
if (scriptBinding)
readProperty(scriptBinding);
}
}
void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding *uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
setSourceLocation(uiScriptBinding->firstSourceLocation());
const QString name = toString(uiScriptBinding->qualifiedId);
const QVariant value = parsePropertyScriptBinding(uiScriptBinding);
propertyDefinition(name, value);
}
QVariant SimpleAbstractStreamReader::parsePropertyScriptBinding(AST::UiScriptBinding *uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
AST::ExpressionStatement *expStmt = AST::cast<AST::ExpressionStatement *>(uiScriptBinding->statement);
if (!expStmt) {
addError(tr("Expected expression statement after colon."), uiScriptBinding->statement->firstSourceLocation());
return QVariant();
} }
return parsePropertyExpression(expStmt->expression); QStringList SimpleAbstractStreamReader::errors() const { return m_errors; }
}
QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode *expressionNode) void SimpleAbstractStreamReader::addError(const QString &error,
{ const SourceLocation &sourceLocation)
Q_ASSERT(expressionNode); {
m_errors << QString::fromLatin1("%1:%2: %3\n")
AST::ArrayPattern *arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode); .arg(QString::number(sourceLocation.startLine),
QString::number(sourceLocation.startColumn),
if (arrayLiteral) { error);
QList<QVariant> variantList;
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
} }
AST::StringLiteral *stringLiteral = AST::cast<AST::StringLiteral *>(expressionNode); SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const
if (stringLiteral) {
return stringLiteral->value.toString(); return m_currentSourceLocation;
}
AST::TrueLiteral *trueLiteral = AST::cast<AST::TrueLiteral *>(expressionNode); bool SimpleAbstractStreamReader::readDocument(AST::UiProgram * ast)
if (trueLiteral) {
return true; if (!ast) {
addError(tr("Could not parse document."));
return false;
}
AST::FalseLiteral *falseLiteral = AST::cast<AST::FalseLiteral *>(expressionNode); AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(
if (falseLiteral) ast->members->member);
return false; if (!uiObjectDefinition) {
addError(tr("Expected document to contain a single object definition."));
return false;
}
readChild(uiObjectDefinition);
AST::NumericLiteral *numericLiteral = AST::cast<AST::NumericLiteral *>(expressionNode); m_source.clear();
if (numericLiteral)
return numericLiteral->value;
return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation()); return errors().isEmpty();
} }
void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation) void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition * uiObjectDefinition)
{ {
m_currentSourceLocation = sourceLocation; Q_ASSERT(uiObjectDefinition);
}
QString SimpleAbstractStreamReader::textAt(const SourceLocation &from, for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it;
const SourceLocation &to) it = it->next) {
{ AST::UiObjectMember *member = it->member;
return m_source.mid(from.offset, to.end() - from.begin()); AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(
} member);
if (uiObjectDefinition)
readChild(uiObjectDefinition);
}
}
SimpleReader::SimpleReader() void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition * uiObjectDefinition)
{ {
} Q_ASSERT(uiObjectDefinition);
SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName) setSourceLocation(uiObjectDefinition->firstSourceLocation());
{
SimpleAbstractStreamReader::readFile(fileName);
return m_rootNode;
}
SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source) elementStart(toString(uiObjectDefinition->qualifiedTypeNameId),
{ toSourceLocation(uiObjectDefinition->qualifiedTypeNameId));
SimpleAbstractStreamReader::readFromSource(source);
return m_rootNode;
}
void SimpleReader::elementStart(const QString &name) readProperties(uiObjectDefinition);
{ readChildren(uiObjectDefinition);
qCDebug(simpleReaderLog) << "elementStart()" << name;
SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, m_currentNode); elementEnd();
}
if (newNode->isRoot()) void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition * uiObjectDefinition)
m_rootNode = newNode; {
Q_ASSERT(uiObjectDefinition);
Q_ASSERT(newNode->isValid()); for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it;
it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(member);
if (scriptBinding)
readProperty(scriptBinding);
}
}
m_currentNode = newNode; void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding * uiScriptBinding)
} {
Q_ASSERT(uiScriptBinding);
void SimpleReader::elementEnd() setSourceLocation(uiScriptBinding->firstSourceLocation());
{
Q_ASSERT(m_currentNode);
qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name(); const QString name = toString(uiScriptBinding->qualifiedId);
auto nameLoc = toSourceLocation(uiScriptBinding->qualifiedId);
auto value = parsePropertyScriptBinding(uiScriptBinding);
m_currentNode = m_currentNode.toStrongRef().data()->parent(); propertyDefinition(name, nameLoc, value.first, value.second);
} }
void SimpleReader::propertyDefinition(const QString &name, const QVariant &value) std::pair<QVariant, SourceLocation> SimpleAbstractStreamReader::parsePropertyScriptBinding(
{ AST::UiScriptBinding * uiScriptBinding)
Q_ASSERT(m_currentNode); {
Q_ASSERT(uiScriptBinding);
qCDebug(simpleReaderLog) << "propertyDefinition()" << m_currentNode.toStrongRef().data()->name() << name << value; AST::ExpressionStatement *expStmt = AST::cast<AST::ExpressionStatement *>(
uiScriptBinding->statement);
if (!expStmt) {
addError(tr("Expected expression statement after colon."),
uiScriptBinding->statement->firstSourceLocation());
return std::make_pair(QVariant(), SourceLocation());
}
if (m_currentNode.toStrongRef().data()->propertyNames().contains(name)) return std::make_pair(parsePropertyExpression(expStmt->expression),
addError(tr("Property is defined twice."), currentSourceLocation()); toSourceLocation(expStmt->firstSourceLocation(),
expStmt->lastSourceLocation()));
}
m_currentNode.toStrongRef().data()->setProperty(name, value); QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode
} * expressionNode)
{
Q_ASSERT(expressionNode);
AST::ArrayPattern *arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode);
if (arrayLiteral) {
QList<QVariant> variantList;
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
}
AST::StringLiteral *stringLiteral = AST::cast<AST::StringLiteral *>(expressionNode);
if (stringLiteral)
return stringLiteral->value.toString();
AST::TrueLiteral *trueLiteral = AST::cast<AST::TrueLiteral *>(expressionNode);
if (trueLiteral)
return true;
AST::FalseLiteral *falseLiteral = AST::cast<AST::FalseLiteral *>(expressionNode);
if (falseLiteral)
return false;
AST::NumericLiteral *numericLiteral = AST::cast<AST::NumericLiteral *>(expressionNode);
if (numericLiteral)
return numericLiteral->value;
return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation());
}
void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation)
{
m_currentSourceLocation = sourceLocation;
}
QString SimpleAbstractStreamReader::textAt(const SourceLocation &from, const SourceLocation &to)
{
return m_source.mid(from.offset, to.end() - from.begin());
}
SimpleReader::SimpleReader() {}
SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName)
{
SimpleAbstractStreamReader::readFile(fileName);
return m_rootNode;
}
SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source)
{
SimpleAbstractStreamReader::readFromSource(source);
return m_rootNode;
}
void SimpleReader::elementStart(const QString &name, const SourceLocation &nameLocation)
{
qCDebug(simpleReaderLog) << "elementStart()" << name;
SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, nameLocation, m_currentNode);
if (newNode->isRoot())
m_rootNode = newNode;
Q_ASSERT(newNode->isValid());
m_currentNode = newNode;
}
void SimpleReader::elementEnd()
{
Q_ASSERT(m_currentNode);
qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name();
m_currentNode = m_currentNode.toStrongRef().data()->parent();
}
void SimpleReader::propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
{
Q_ASSERT(m_currentNode);
qCDebug(simpleReaderLog) << "propertyDefinition()"
<< m_currentNode.toStrongRef().data()->name() << name << value;
if (m_currentNode.toStrongRef().data()->propertyNames().contains(name)) {
auto previousSourceLoc = m_currentNode.toStrongRef().data()->property(name).nameLocation;
addError(tr("Property is defined twice, previous definition at %1:%2")
.arg(QString::number(previousSourceLoc.startLine),
QString::number(previousSourceLoc.startColumn)),
currentSourceLocation());
}
m_currentNode.toStrongRef().data()->setProperty(name, nameLocation, value, valueLocation);
}
} // namespace QmlJS } // namespace QmlJS

View File

@@ -26,13 +26,18 @@
#pragma once #pragma once
#include <qmljs/qmljs_global.h> #include <qmljs/qmljs_global.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#ifdef QT_CREATOR
#include <qmljs/parser/qmljsastfwd_p.h>
#else
#include <parser/qqmljsastfwd_p.h>
#endif
#include <QHash> #include <QHash>
#include <QList> #include <QList>
#include <QStringList>
#include <QSharedPointer> #include <QSharedPointer>
#include <QStringList>
#include <QVariant>
#include <QWeakPointer> #include <QWeakPointer>
// for Q_DECLARE_TR_FUNCTIONS // for Q_DECLARE_TR_FUNCTIONS
@@ -40,15 +45,31 @@
namespace QmlJS { namespace QmlJS {
#ifndef QT_CREATOR
using SourceLocation = QQmlJS::SourceLocation;
#endif
class QMLJS_EXPORT SimpleReaderNode class QMLJS_EXPORT SimpleReaderNode
{ {
public: public:
struct Property
{
QVariant value;
SourceLocation nameLocation;
SourceLocation valueLocation;
bool isValid() const { return !value.isNull() && value.isValid(); }
bool isDefaultValue() const
{
return !value.isNull() && !nameLocation.isValid() && !valueLocation.isValid();
}
};
typedef QSharedPointer<SimpleReaderNode> Ptr; typedef QSharedPointer<SimpleReaderNode> Ptr;
typedef QWeakPointer<SimpleReaderNode> WeakPtr; typedef QWeakPointer<SimpleReaderNode> WeakPtr;
typedef QHash<QString, QVariant> PropertyHash; typedef QHash<QString, Property> PropertyHash;
typedef QList<Ptr> List; typedef QList<Ptr> List;
QVariant property(const QString &name) const; Property property(const QString &name) const;
QStringList propertyNames() const; QStringList propertyNames() const;
PropertyHash properties() const; PropertyHash properties() const;
bool isRoot() const; bool isRoot() const;
@@ -56,16 +77,21 @@ public:
static Ptr invalidNode(); static Ptr invalidNode();
WeakPtr parent() const; WeakPtr parent() const;
QString name() const; QString name() const;
SourceLocation nameLocation() const;
const List children() const; const List children() const;
protected: protected:
SimpleReaderNode(); SimpleReaderNode();
SimpleReaderNode(const QString &name, WeakPtr parent); SimpleReaderNode(const QString &name, const SourceLocation &nameLocation, WeakPtr parent);
static Ptr create(const QString &name, WeakPtr parent); static Ptr create(const QString &name, const SourceLocation &nameLocation, WeakPtr parent);
void setProperty(const QString &name, const QVariant &value); void setProperty(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation);
private: private:
const QString m_name; const QString m_name;
const SourceLocation m_nameLocation;
PropertyHash m_properties; PropertyHash m_properties;
const WeakPtr m_parentNode; const WeakPtr m_parentNode;
List m_children; List m_children;
@@ -74,12 +100,17 @@ private:
friend class SimpleReader; friend class SimpleReader;
}; };
#ifndef QT_CREATOR
using namespace QQmlJS;
#endif
class QMLJS_EXPORT SimpleAbstractStreamReader class QMLJS_EXPORT SimpleAbstractStreamReader
{ {
Q_DECLARE_TR_FUNCTIONS(QmlJS::SimpleAbstractStreamReader) Q_DECLARE_TR_FUNCTIONS(QmlJS::SimpleAbstractStreamReader)
public: public:
SimpleAbstractStreamReader(); SimpleAbstractStreamReader();
virtual ~SimpleAbstractStreamReader();
bool readFile(const QString &fileName); bool readFile(const QString &fileName);
bool readFromSource(const QString &source); bool readFromSource(const QString &source);
QStringList errors() const; QStringList errors() const;
@@ -88,9 +119,13 @@ protected:
void addError(const QString &error, const SourceLocation &sourceLocation = SourceLocation()); void addError(const QString &error, const SourceLocation &sourceLocation = SourceLocation());
SourceLocation currentSourceLocation() const; SourceLocation currentSourceLocation() const;
virtual void elementStart(const QString &name) = 0; virtual void elementStart(const QString &name, const SourceLocation &nameLocation) = 0;
virtual void elementEnd() = 0; virtual void elementEnd() = 0;
virtual void propertyDefinition(const QString &name, const QVariant &value) = 0; virtual void propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
= 0;
private: private:
bool readDocument(AST::UiProgram *ast); bool readDocument(AST::UiProgram *ast);
@@ -98,7 +133,8 @@ private:
void readChild(AST::UiObjectDefinition *uiObjectDefinition); void readChild(AST::UiObjectDefinition *uiObjectDefinition);
void readProperties(AST::UiObjectDefinition *ast); void readProperties(AST::UiObjectDefinition *ast);
void readProperty(AST::UiScriptBinding *uiScriptBinding); void readProperty(AST::UiScriptBinding *uiScriptBinding);
QVariant parsePropertyScriptBinding(AST::UiScriptBinding *ExpressionNode); std::pair<QVariant, SourceLocation> parsePropertyScriptBinding(
AST::UiScriptBinding *ExpressionNode);
QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode); QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode);
void setSourceLocation(const SourceLocation &sourceLocation); void setSourceLocation(const SourceLocation &sourceLocation);
QString textAt(const SourceLocation &from, const SourceLocation &to); QString textAt(const SourceLocation &from, const SourceLocation &to);
@@ -118,9 +154,12 @@ public:
SimpleReaderNode::Ptr readFromSource(const QString &source); SimpleReaderNode::Ptr readFromSource(const QString &source);
protected: protected:
void elementStart(const QString &name) override; void elementStart(const QString &name, const SourceLocation &nameLocation) override;
void elementEnd() override; void elementEnd() override;
void propertyDefinition(const QString &name, const QVariant &value) override; void propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation) override;
private: private:
SimpleReaderNode::Ptr m_rootNode; SimpleReaderNode::Ptr m_rootNode;

View File

@@ -595,9 +595,9 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) { for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
if (node->propertyNames().contains("separateSection")) if (node->propertyNames().contains("separateSection"))
separateSectionTypes.append(variantToStringList(node->property("typeNames"))); separateSectionTypes.append(variantToStringList(node->property("typeNames").value));
allTypes.append(variantToStringList(node->property("typeNames"))); allTypes.append(variantToStringList(node->property("typeNames").value));
} }
const QList<PropertyName> allProperties = type.propertyNames(); const QList<PropertyName> allProperties = type.propertyNames();
@@ -666,8 +666,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
QString filledTemplate; QString filledTemplate;
for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) { for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) {
// Check if we have a template for the type // Check if we have a template for the type
if (variantToStringList(n->property(QStringLiteral("typeNames"))).contains(QString::fromLatin1(typeName))) { if (variantToStringList(n->property(QStringLiteral("typeNames")).value).contains(QString::fromLatin1(typeName))) {
const QString fileName = propertyTemplatesPath() + n->property(QStringLiteral("sourceFile")).toString(); const QString fileName = propertyTemplatesPath() + n->property(QStringLiteral("sourceFile")).value.toString();
QFile file(fileName); QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QString source = QString::fromUtf8(file.readAll()); QString source = QString::fromUtf8(file.readAll());
@@ -682,7 +682,7 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type,
}; };
// QML specfics preparation // QML specfics preparation
QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports"))); QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports")).value);
QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n'); QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n');
bool emptyTemplate = true; bool emptyTemplate = true;

View File

@@ -54,9 +54,12 @@ public:
void setQualifcation(const TypeName &qualification); void setQualifcation(const TypeName &qualification);
protected: protected:
void elementStart(const QString &name) override; void elementStart(const QString &name, const QmlJS::SourceLocation &nameLocation) override;
void elementEnd() override; void elementEnd() override;
void propertyDefinition(const QString &name, const QVariant &value) override; void propertyDefinition(const QString &name,
const QmlJS::SourceLocation &nameLocation,
const QVariant &value,
const QmlJS::SourceLocation &valueLocation) override;
private: private:
enum ParserSate { Error, enum ParserSate { Error,

View File

@@ -87,7 +87,7 @@ void MetaInfoReader::setQualifcation(const TypeName &qualification)
m_qualication = qualification; m_qualication = qualification;
} }
void MetaInfoReader::elementStart(const QString &name) void MetaInfoReader::elementStart(const QString &name, const QmlJS::SourceLocation &nameLocation)
{ {
switch (parserState()) { switch (parserState()) {
case ParsingDocument: setParserState(readDocument(name)); break; case ParsingDocument: setParserState(readDocument(name)); break;
@@ -128,7 +128,10 @@ void MetaInfoReader::elementEnd()
} }
} }
void MetaInfoReader::propertyDefinition(const QString &name, const QVariant &value) void MetaInfoReader::propertyDefinition(const QString &name,
const QmlJS::SourceLocation &nameLocation,
const QVariant &value,
const QmlJS::SourceLocation &valueLocation)
{ {
switch (parserState()) { switch (parserState()) {
case ParsingType: readTypeProperty(name, value); break; case ParsingType: readTypeProperty(name, value); break;

View File

@@ -1161,7 +1161,7 @@ void checkNode(const QmlJS::SimpleReaderNode::Ptr &node, RewriterView *view)
if (!node->propertyNames().contains("i")) if (!node->propertyNames().contains("i"))
return; return;
const int index = node->property("i").toInt(); const int index = node->property("i").value.toInt();
const ModelNode modelNode = view->getNodeForCanonicalIndex(index); const ModelNode modelNode = view->getNodeForCanonicalIndex(index);
@@ -1174,7 +1174,7 @@ void checkNode(const QmlJS::SimpleReaderNode::Ptr &node, RewriterView *view)
if (i.key() != "i") { if (i.key() != "i") {
const PropertyName name = fixUpIllegalChars(i.key()).toUtf8(); const PropertyName name = fixUpIllegalChars(i.key()).toUtf8();
if (!modelNode.hasAuxiliaryData(name)) if (!modelNode.hasAuxiliaryData(name))
modelNode.setAuxiliaryData(name, i.value()); modelNode.setAuxiliaryData(name, i.value().value);
} }
} }

View File

@@ -37,20 +37,20 @@ namespace QmlDesigner {
static QString readProperty(const QString property, const QmlJS::SimpleReaderNode::Ptr &node) static QString readProperty(const QString property, const QmlJS::SimpleReaderNode::Ptr &node)
{ {
const QVariant propertyVar = node->property(property); const auto propertyVar = node->property(property);
if (!propertyVar.isNull() && propertyVar.isValid()) if (propertyVar.isValid())
return propertyVar.value<QString>(); return propertyVar.value.value<QString>();
return {}; return {};
} }
static QStringList readPropertyList(const QString &property, const QmlJS::SimpleReaderNode::Ptr &node) static QStringList readPropertyList(const QString &property, const QmlJS::SimpleReaderNode::Ptr &node)
{ {
const QVariant propertyVar = node->property(property); const auto propertyVar = node->property(property);
if (!propertyVar.isNull() && propertyVar.isValid()) if (propertyVar.isValid())
return propertyVar.value<QStringList>(); return propertyVar.value.value<QStringList>();
return {}; return {};
} }
@@ -99,30 +99,31 @@ void DesignerMcuManager::readMetadata()
return; return;
} }
const QVariant defaultVersion = metadata->property("defaultVersion"); const QmlJS::SimpleReaderNode::Property defaultVersion = metadata->property("defaultVersion");
if (!defaultVersion.isNull() && defaultVersion.isValid()) {
if (defaultVersion.isValid()) {
for (const auto& version : versions) { for (const auto& version : versions) {
Version newVersion; Version newVersion;
const QVariant vId = version->property("id"); const auto vId = version->property("id");
if (vId.isNull() || !vId.isValid()) if (!vId.isValid())
continue; continue;
const QVariant vName = version->property("name"); const auto vName = version->property("name");
if (!vName.isNull() && vName.isValid()) if (vName.isValid())
newVersion.name = vName.value<QString>(); newVersion.name = vName.value.value<QString>();
else else
continue; continue;
const QVariant vPath = version->property("path"); const auto vPath = version->property("path");
if (!vPath.isNull() && vPath.isValid()) if (vPath.isValid())
newVersion.fileName = vPath.value<QString>(); newVersion.fileName = vPath.value.value<QString>();
else else
continue; continue;
m_versionsList.push_back(newVersion); m_versionsList.push_back(newVersion);
if (vId == defaultVersion) if (vId.value == defaultVersion.value)
m_defaultVersion = newVersion; m_defaultVersion = newVersion;
} }
} }
@@ -172,10 +173,10 @@ void DesignerMcuManager::readVersionData(const DesignerMcuManager::Version &vers
if (child->propertyNames().contains("allowedProperties")) { if (child->propertyNames().contains("allowedProperties")) {
ItemProperties allowedProperties; ItemProperties allowedProperties;
const QVariant childrenPropertyVar = child->property("allowChildren"); const auto childrenPropertyVar = child->property("allowChildren");
if (!childrenPropertyVar.isNull() && childrenPropertyVar.isValid()) if (childrenPropertyVar.isValid())
allowedProperties.allowChildren = childrenPropertyVar.toBool(); allowedProperties.allowChildren = childrenPropertyVar.value.toBool();
allowedProperties.properties = readPropertyList("allowedProperties", child); allowedProperties.properties = readPropertyList("allowedProperties", child);

View File

@@ -39,24 +39,30 @@ namespace {
QmlProjectManager::FileFilterBaseItem *setupFileFilterItem(QmlProjectManager::FileFilterBaseItem *fileFilterItem, const QmlJS::SimpleReaderNode::Ptr &node) QmlProjectManager::FileFilterBaseItem *setupFileFilterItem(QmlProjectManager::FileFilterBaseItem *fileFilterItem, const QmlJS::SimpleReaderNode::Ptr &node)
{ {
const QVariant directoryProperty = node->property(QLatin1String("directory")); const auto directoryProperty = node->property(QLatin1String("directory"));
if (directoryProperty.isValid()) if (directoryProperty.isValid())
fileFilterItem->setDirectory(directoryProperty.toString()); fileFilterItem->setDirectory(directoryProperty.value.toString());
const QVariant recursiveProperty = node->property(QLatin1String("recursive")); const auto recursiveProperty = node->property(QLatin1String("recursive"));
if (recursiveProperty.isValid()) if (recursiveProperty.isValid())
fileFilterItem->setRecursive(recursiveProperty.toBool()); fileFilterItem->setRecursive(recursiveProperty.value.toBool());
const QVariant pathsProperty = node->property(QLatin1String("paths")); const auto pathsProperty = node->property(QLatin1String("paths"));
if (pathsProperty.isValid()) if (pathsProperty.isValid())
fileFilterItem->setPathsProperty(pathsProperty.toStringList()); fileFilterItem->setPathsProperty(pathsProperty.value.toStringList());
const QVariant filterProperty = node->property(QLatin1String("filter")); // "paths" and "files" have the same functionality
const auto filesProperty = node->property(QLatin1String("files"));
if (filesProperty.isValid())
fileFilterItem->setPathsProperty(filesProperty.value.toStringList());
const auto filterProperty = node->property(QLatin1String("filter"));
if (filterProperty.isValid()) if (filterProperty.isValid())
fileFilterItem->setFilter(filterProperty.toString()); fileFilterItem->setFilter(filterProperty.value.toString());
if (debug) if (debug)
qDebug() << "directory:" << directoryProperty << "recursive" << recursiveProperty << "paths" << pathsProperty; qDebug() << "directory:" << directoryProperty.value << "recursive" << recursiveProperty.value
<< "paths" << pathsProperty.value << "files" << filesProperty.value;
return fileFilterItem; return fileFilterItem;
} }
@@ -81,36 +87,36 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
if (rootNode->name() == QLatin1String("Project")) { if (rootNode->name() == QLatin1String("Project")) {
auto projectItem = new QmlProjectItem; auto projectItem = new QmlProjectItem;
const QVariant mainFileProperty = rootNode->property(QLatin1String("mainFile")); const auto mainFileProperty = rootNode->property(QLatin1String("mainFile"));
if (mainFileProperty.isValid()) if (mainFileProperty.isValid())
projectItem->setMainFile(mainFileProperty.toString()); projectItem->setMainFile(mainFileProperty.value.toString());
const QVariant importPathsProperty = rootNode->property(QLatin1String("importPaths")); const auto importPathsProperty = rootNode->property(QLatin1String("importPaths"));
if (importPathsProperty.isValid()) if (importPathsProperty.isValid())
projectItem->setImportPaths(importPathsProperty.toStringList()); projectItem->setImportPaths(importPathsProperty.value.toStringList());
const QVariant fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors")); const auto fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors"));
if (fileSelectorsProperty.isValid()) if (fileSelectorsProperty.isValid())
projectItem->setFileSelectors(fileSelectorsProperty.toStringList()); projectItem->setFileSelectors(fileSelectorsProperty.value.toStringList());
const QVariant forceFreeTypeProperty = rootNode->property("forceFreeType"); const auto forceFreeTypeProperty = rootNode->property("forceFreeType");
if (forceFreeTypeProperty.isValid()) if (forceFreeTypeProperty.isValid())
projectItem->setForceFreeType(forceFreeTypeProperty.toBool()); projectItem->setForceFreeType(forceFreeTypeProperty.value.toBool());
const QVariant targetDirectoryPropery = rootNode->property("targetDirectory"); const auto targetDirectoryPropery = rootNode->property("targetDirectory");
if (targetDirectoryPropery.isValid()) if (targetDirectoryPropery.isValid())
projectItem->setTargetDirectory(targetDirectoryPropery.toString()); projectItem->setTargetDirectory(targetDirectoryPropery.value.toString());
const QVariant qtForMCUProperty = rootNode->property("qtForMCUs"); const auto qtForMCUProperty = rootNode->property("qtForMCUs");
if (qtForMCUProperty.isValid() && qtForMCUProperty.toBool()) if (qtForMCUProperty.isValid() && qtForMCUProperty.value.toBool())
projectItem->setQtForMCUs(qtForMCUProperty.toBool()); projectItem->setQtForMCUs(qtForMCUProperty.value.toBool());
const QVariant qt6ProjectProperty = rootNode->property("qt6Project"); const auto qt6ProjectProperty = rootNode->property("qt6Project");
if (qt6ProjectProperty.isValid() && qt6ProjectProperty.toBool()) if (qt6ProjectProperty.isValid() && qt6ProjectProperty.value.toBool())
projectItem->setQt6Project(qt6ProjectProperty.toBool()); projectItem->setQt6Project(qt6ProjectProperty.value.toBool());
if (debug) if (debug)
qDebug() << "importPath:" << importPathsProperty << "mainFile:" << mainFileProperty; qDebug() << "importPath:" << importPathsProperty.value << "mainFile:" << mainFileProperty.value;
foreach (const QmlJS::SimpleReaderNode::Ptr &childNode, rootNode->children()) { foreach (const QmlJS::SimpleReaderNode::Ptr &childNode, rootNode->children()) {
if (debug) if (debug)
@@ -132,7 +138,7 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
const auto properties = childNode->properties(); const auto properties = childNode->properties();
auto i = properties.constBegin(); auto i = properties.constBegin();
while (i != properties.constEnd()) { while (i != properties.constEnd()) {
projectItem->addToEnviroment(i.key(), i.value().toString()); projectItem->addToEnviroment(i.key(), i.value().value.toString());
++i; ++i;
} }
} else { } else {

View File

@@ -8546,14 +8546,14 @@ static void checkNode(QmlJS::SimpleReaderNode::Ptr node, TestRewriterView *view)
{ {
QVERIFY(node); QVERIFY(node);
QVERIFY(node->propertyNames().contains("i")); QVERIFY(node->propertyNames().contains("i"));
const int internalId = node->property("i").toInt(); const int internalId = node->property("i").value.toInt();
const ModelNode modelNode = view->modelNodeForInternalId(internalId); const ModelNode modelNode = view->modelNodeForInternalId(internalId);
QVERIFY(modelNode.isValid()); QVERIFY(modelNode.isValid());
auto properties = node->properties(); auto properties = node->properties();
for (auto i = properties.begin(); i != properties.end(); ++i) { for (auto i = properties.begin(); i != properties.end(); ++i) {
if (i.key() != "i") if (i.key() != "i")
QCOMPARE(i.value(), modelNode.auxiliaryData(i.key().toUtf8())); QCOMPARE(i.value().value, modelNode.auxiliaryData(i.key().toUtf8()));
} }
checkChildNodes(node, view); checkChildNodes(node, view);

View File

@@ -77,13 +77,13 @@ void tst_SimpleReader::testWellFormed()
QCOMPARE(rootNode->properties().count(), 1); QCOMPARE(rootNode->properties().count(), 1);
QVERIFY(rootNode->properties().contains("propertyBlah")); QVERIFY(rootNode->properties().contains("propertyBlah"));
QCOMPARE(rootNode->property("property01").toBool(), false); QCOMPARE(rootNode->property("property01").value.toBool(), false);
QVERIFY(rootNode->children().first()->isValid()); QVERIFY(rootNode->children().first()->isValid());
QVERIFY(!rootNode->children().first()->isRoot()); QVERIFY(!rootNode->children().first()->isRoot());
QVERIFY(rootNode->children().first()->properties().contains("property01")); QVERIFY(rootNode->children().first()->properties().contains("property01"));
QCOMPARE(rootNode->children().first()->property("property01").toInt(), 10); QCOMPARE(rootNode->children().first()->property("property01").value.toInt(), 10);
SimpleReaderNode::Ptr secondChild = rootNode->children().at(1); SimpleReaderNode::Ptr secondChild = rootNode->children().at(1);
@@ -93,7 +93,7 @@ void tst_SimpleReader::testWellFormed()
QCOMPARE(secondChild->name(), QLatin1String("ChildNode")); QCOMPARE(secondChild->name(), QLatin1String("ChildNode"));
QVERIFY(secondChild->properties().contains("propertyString")); QVERIFY(secondChild->properties().contains("propertyString"));
QCOMPARE(secondChild->property("propertyString").toString(), QLatin1String("str")); QCOMPARE(secondChild->property("propertyString").value.toString(), QLatin1String("str"));
QCOMPARE(secondChild->children().count(), 1); QCOMPARE(secondChild->children().count(), 1);
@@ -105,7 +105,7 @@ void tst_SimpleReader::testWellFormed()
QCOMPARE(innerChild->name(), QLatin1String("InnerChild")); QCOMPARE(innerChild->name(), QLatin1String("InnerChild"));
QVERIFY(innerChild->properties().contains("test")); QVERIFY(innerChild->properties().contains("test"));
QCOMPARE(innerChild->property("test").toString(), QLatin1String("test")); QCOMPARE(innerChild->property("test").value.toString(), QLatin1String("test"));
weak01 = rootNode; weak01 = rootNode;
weak02 = secondChild; weak02 = secondChild;
@@ -170,7 +170,7 @@ void tst_SimpleReader::testIllFormed02()
QCOMPARE(firstChild->properties().count(), 1); QCOMPARE(firstChild->properties().count(), 1);
QVERIFY(firstChild->properties().contains("property01")); QVERIFY(firstChild->properties().contains("property01"));
QCOMPARE(firstChild->property("property01").toString(), QLatin1String("20")); QCOMPARE(firstChild->property("property01").value.toString(), QLatin1String("20"));
} }
void tst_SimpleReader::testArrays() void tst_SimpleReader::testArrays()
@@ -194,7 +194,7 @@ void tst_SimpleReader::testArrays()
QVERIFY(rootNode->isValid()); QVERIFY(rootNode->isValid());
QVERIFY(rootNode->isRoot()); QVERIFY(rootNode->isRoot());
QCOMPARE(rootNode->property("propertyArray"), variant); QCOMPARE(rootNode->property("propertyArray").value, variant);
SimpleReaderNode::Ptr firstChild = rootNode->children().at(0); SimpleReaderNode::Ptr firstChild = rootNode->children().at(0);
@@ -202,13 +202,13 @@ void tst_SimpleReader::testArrays()
QVERIFY(firstChild); QVERIFY(firstChild);
QVERIFY(firstChild->isValid()); QVERIFY(firstChild->isValid());
QVERIFY(!firstChild->isRoot()); QVERIFY(!firstChild->isRoot());
QCOMPARE(firstChild->property("propertyArray"), variant); QCOMPARE(firstChild->property("propertyArray").value, variant);
QList<QVariant> variantList2; QList<QVariant> variantList2;
variantList2 << QVariant(QLatin1String("string03")) << variant; variantList2 << QVariant(QLatin1String("string03")) << variant;
const QVariant variant2 = variantList2; const QVariant variant2 = variantList2;
QCOMPARE(firstChild->property("propertyArrayMixed"), variant2); QCOMPARE(firstChild->property("propertyArrayMixed").value, variant2);
} }
void tst_SimpleReader::testBug01() void tst_SimpleReader::testBug01()