Qml: Add script element for return statements
Implement and test the DOM representation of a JS return statement. Task-number: QTBUG-100084 Task-number: QTBUG-111415 Change-Id: I2c11c0b9be3c93cf5be2bd9db5575335d4be19c1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
7d8ac7c2d3
commit
eba8eb2305
|
@ -91,6 +91,7 @@ class VariableDeclaration;
|
|||
class VariableDeclarationEntry;
|
||||
// TODO: add new script classes here, as qqmldomitem_p.h cannot include qqmldomscriptelements_p.h
|
||||
// without creating circular dependencies
|
||||
class ReturnStatement;
|
||||
|
||||
} // end namespace ScriptElements
|
||||
|
||||
|
|
|
@ -1256,6 +1256,30 @@ void QQmlDomAstCreator::endVisit(AST::IfStatement *ifStatement)
|
|||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
bool QQmlDomAstCreator::visit(AST::ReturnStatement *)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQmlDomAstCreator::endVisit(AST::ReturnStatement *returnStatement)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return;
|
||||
|
||||
auto current = makeScriptElement<ScriptElements::ReturnStatement>(returnStatement);
|
||||
|
||||
if (returnStatement->expression) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->setExpression(currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
static const DomEnvironment *environmentFrom(MutableDomItem &qmlFile)
|
||||
{
|
||||
auto top = qmlFile.top();
|
||||
|
|
|
@ -303,6 +303,9 @@ public:
|
|||
bool visit(AST::Block *block) override;
|
||||
void endVisit(AST::Block *) override;
|
||||
|
||||
bool visit(AST::ReturnStatement *block) override;
|
||||
void endVisit(AST::ReturnStatement *) override;
|
||||
|
||||
bool visit(AST::ForStatement *forStatement) override;
|
||||
void endVisit(AST::ForStatement *forStatement) override;
|
||||
|
||||
|
|
|
@ -200,6 +200,7 @@ enum class DomType {
|
|||
ScriptFunctionDeclaration,
|
||||
ScriptVariableDeclaration,
|
||||
ScriptVariableDeclarationEntry,
|
||||
ScriptReturnStatement,
|
||||
|
||||
ScriptElementStop, // marker to check if a DomType is a scriptelement or not
|
||||
};
|
||||
|
|
|
@ -730,7 +730,8 @@ public:
|
|||
VariantOfPointer<ScriptElements::BlockStatement, ScriptElements::IdentifierExpression,
|
||||
ScriptElements::ForStatement, ScriptElements::BinaryExpression,
|
||||
ScriptElements::VariableDeclarationEntry, ScriptElements::Literal,
|
||||
ScriptElements::IfStatement, ScriptElements::VariableDeclaration>;
|
||||
ScriptElements::IfStatement,
|
||||
ScriptElements::VariableDeclaration, ScriptElements::ReturnStatement>;
|
||||
|
||||
template<typename T>
|
||||
static ScriptElementVariant fromElement(T element)
|
||||
|
|
|
@ -278,3 +278,22 @@ void VariableDeclaration::createFileLocations(FileLocations::Tree base)
|
|||
BaseT::createFileLocations(base);
|
||||
m_declarations.createFileLocations(base);
|
||||
}
|
||||
|
||||
bool ReturnStatement::iterateDirectSubpaths(DomItem &self, DirectVisitor visitor)
|
||||
{
|
||||
bool cont = true;
|
||||
cont &= wrap(self, visitor, Fields::expression, m_expression);
|
||||
return cont;
|
||||
}
|
||||
|
||||
void ReturnStatement::updatePathFromOwner(Path p)
|
||||
{
|
||||
BaseT::updatePathFromOwner(p);
|
||||
m_expression.base()->updatePathFromOwner(p.field(Fields::expression));
|
||||
}
|
||||
|
||||
void ReturnStatement::createFileLocations(FileLocations::Tree base)
|
||||
{
|
||||
BaseT::createFileLocations(base);
|
||||
m_expression.base()->createFileLocations(base);
|
||||
}
|
||||
|
|
|
@ -241,6 +241,24 @@ private:
|
|||
ScriptElementVariant m_alternative;
|
||||
};
|
||||
|
||||
class ReturnStatement : public ScriptElementBase<DomType::ScriptReturnStatement>
|
||||
{
|
||||
public:
|
||||
using BaseT::BaseT;
|
||||
~ReturnStatement() override{};
|
||||
|
||||
// minimal required overload for this to be wrapped as DomItem:
|
||||
bool iterateDirectSubpaths(DomItem &self, DirectVisitor visitor) override;
|
||||
void updatePathFromOwner(Path p) override;
|
||||
void createFileLocations(FileLocations::Tree base) override;
|
||||
|
||||
ScriptElementVariant expression() const { return m_expression; }
|
||||
void setExpression(ScriptElementVariant expression) { m_expression = expression; }
|
||||
|
||||
private:
|
||||
ScriptElementVariant m_expression;
|
||||
};
|
||||
|
||||
class BinaryExpression : public ScriptElementBase<DomType::ScriptBinaryExpression>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -36,7 +36,13 @@ Item {
|
|||
} else {
|
||||
i = 456
|
||||
}
|
||||
}
|
||||
|
||||
function returningFunction() {
|
||||
if (i)
|
||||
return 123;
|
||||
else
|
||||
return 1 + 2;
|
||||
}
|
||||
|
||||
function testForNull() {
|
||||
|
|
|
@ -1246,6 +1246,30 @@ private slots:
|
|||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
DomItem block =
|
||||
rootQmlObject.path(".methods[\"returningFunction\"][0].body.scriptElement");
|
||||
QCOMPARE(block.internalKind(), DomType::ScriptBlockStatement);
|
||||
QCOMPARE(block.field(Fields::statements).indexes(), 1);
|
||||
DomItem conditional = block.field(Fields::statements).index(0);
|
||||
DomItem consequence = conditional.field(Fields::consequence);
|
||||
QCOMPARE(consequence.internalKind(), DomType::ScriptReturnStatement);
|
||||
{
|
||||
DomItem returnValue = consequence.field(Fields::expression);
|
||||
QCOMPARE(returnValue.internalKind(), DomType::ScriptLiteral);
|
||||
QCOMPARE(returnValue.field(Fields::value).value().toDouble(), 123);
|
||||
}
|
||||
DomItem alternative = conditional.field(Fields::alternative);
|
||||
QCOMPARE(alternative.internalKind(), DomType::ScriptReturnStatement);
|
||||
{
|
||||
DomItem returnValue = alternative.field(Fields::expression);
|
||||
QCOMPARE(returnValue.internalKind(), DomType::ScriptBinaryExpression);
|
||||
QCOMPARE(returnValue.field(Fields::left).field(Fields::value).value().toDouble(),
|
||||
1);
|
||||
QCOMPARE(returnValue.field(Fields::right).field(Fields::value).value().toDouble(),
|
||||
2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue