qmldom: Add dom representations for iteration statement
Implement visits for while, do-while and foreach node types. Allow creating semantic scope them to find usages/definitions of the script elements within those statements. Add tests for each iteration types implemented. Exclude iterationStatements.qml file from tst_qmlformat test since it includes object destructuring patterns that qmlformat currently doesn't support. Task-number: QTBUG-92876 Task-number: QTBUG-113334 Change-Id: I7936a6b4542c7498e44bdda842a2501cd35b77fa Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
955a162a54
commit
c98719b8ca
|
@ -1977,6 +1977,101 @@ void QQmlDomAstCreator::endVisit(AST::SwitchStatement *exp)
|
|||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
bool QQmlDomAstCreator::visit(AST::WhileStatement *)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQmlDomAstCreator::endVisit(AST::WhileStatement *exp)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return;
|
||||
|
||||
auto current = makeGenericScriptElement(exp, DomType::ScriptWhileStatement);
|
||||
|
||||
if (exp->statement) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
if (exp->expression) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
bool QQmlDomAstCreator::visit(AST::DoWhileStatement *)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQmlDomAstCreator::endVisit(AST::DoWhileStatement *exp)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return;
|
||||
|
||||
auto current = makeGenericScriptElement(exp, DomType::ScriptDoWhileStatement);
|
||||
|
||||
if (exp->expression) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
if (exp->statement) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
bool QQmlDomAstCreator::visit(AST::ForEachStatement *)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQmlDomAstCreator::endVisit(AST::ForEachStatement *exp)
|
||||
{
|
||||
if (!m_enableScriptExpressions)
|
||||
return;
|
||||
|
||||
auto current = makeGenericScriptElement(exp, DomType::ScriptForEachStatement);
|
||||
|
||||
if (exp->statement) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
if (exp->expression) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
if (exp->lhs) {
|
||||
Q_SCRIPTELEMENT_EXIT_IF(scriptNodeStack.isEmpty());
|
||||
current->insertChild(Fields::bindingElement, currentScriptNodeEl().takeVariant());
|
||||
removeCurrentScriptNode({});
|
||||
}
|
||||
|
||||
pushScriptElement(current);
|
||||
}
|
||||
|
||||
static const DomEnvironment *environmentFrom(MutableDomItem &qmlFile)
|
||||
{
|
||||
auto top = qmlFile.top();
|
||||
|
@ -2040,6 +2135,9 @@ QQmlJSASTClassListToVisit
|
|||
switch (topOfStack.kind) {
|
||||
case DomType::ScriptBlockStatement:
|
||||
case DomType::ScriptForStatement:
|
||||
case DomType::ScriptForEachStatement:
|
||||
case DomType::ScriptDoWhileStatement:
|
||||
case DomType::ScriptWhileStatement:
|
||||
case DomType::List:
|
||||
m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
|
||||
break;
|
||||
|
|
|
@ -401,6 +401,15 @@ public:
|
|||
bool visit(AST::SwitchStatement *) override;
|
||||
void endVisit(AST::SwitchStatement *) override;
|
||||
|
||||
bool visit(AST::WhileStatement *) override;
|
||||
void endVisit(AST::WhileStatement *) override;
|
||||
|
||||
bool visit(AST::DoWhileStatement *) override;
|
||||
void endVisit(AST::DoWhileStatement *) override;
|
||||
|
||||
bool visit(AST::ForEachStatement *) override;
|
||||
void endVisit(AST::ForEachStatement *) override;
|
||||
|
||||
// lists of stuff whose children do not need a qqmljsscope: visitation order can be custom
|
||||
bool visit(AST::ArgumentList *) override;
|
||||
bool visit(AST::UiParameterList *) override;
|
||||
|
|
|
@ -219,6 +219,9 @@ enum class DomType {
|
|||
ScriptCaseClauses,
|
||||
ScriptCaseClause,
|
||||
ScriptDefaultClause,
|
||||
ScriptWhileStatement,
|
||||
ScriptDoWhileStatement,
|
||||
ScriptForEachStatement,
|
||||
|
||||
ScriptElementStop, // marker to check if a DomType is a scriptelement or not
|
||||
};
|
||||
|
|
|
@ -155,6 +155,7 @@ void TestQmlformat::initTestCase()
|
|||
|
||||
// qmlformat cannot handle deconstructing arguments
|
||||
m_ignoreFiles << "tests/auto/qmldom/domdata/domitem/callExpressions.qml";
|
||||
m_ignoreFiles << "tests/auto/qmldom/domdata/domitem/iterationStatements.qml";
|
||||
}
|
||||
|
||||
QStringList TestQmlformat::findFiles(const QDir &d)
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
|
||||
function whileStatement() {
|
||||
const i = 10;
|
||||
while (i > 0) {
|
||||
i = i -1;
|
||||
while ( i > 100) {}
|
||||
}
|
||||
|
||||
while (i > 0) i = i-1
|
||||
}
|
||||
|
||||
function doWhile() {
|
||||
let a = 7;
|
||||
do {
|
||||
const b = a;
|
||||
a = a - 1;
|
||||
} while (a > 0)
|
||||
|
||||
do a = a-1; while (a > 0)
|
||||
}
|
||||
|
||||
function forOf() {
|
||||
const iterable = [[1,2], [3,4],]
|
||||
for (var [a,b] of iterable) {
|
||||
|
||||
let t;
|
||||
for (const [a1, , a2, ...rest] of array) {
|
||||
|
||||
}
|
||||
for (const k of [1,2,3,4,,,]) {
|
||||
t += k;
|
||||
}
|
||||
for (t of a) {
|
||||
{}
|
||||
}
|
||||
for (t of a) t += k
|
||||
}
|
||||
}
|
||||
|
||||
function forIn() {
|
||||
const enumerable = {
|
||||
list: [1, 2, 3, 4, 5],
|
||||
name: 'John',
|
||||
age: 25
|
||||
};
|
||||
|
||||
for (var [a,b,c,d] in enumerable) {
|
||||
let t;
|
||||
for (t in enumerable) {
|
||||
{}
|
||||
}
|
||||
for (const [a1, , a2, ...rest] in enumerable.list) {
|
||||
|
||||
}
|
||||
for (let t in enumerable) t += k
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1932,6 +1932,316 @@ private slots:
|
|||
}
|
||||
}
|
||||
|
||||
void iterationStatements()
|
||||
{
|
||||
using namespace Qt::StringLiterals;
|
||||
QString testFile = baseDir + u"/iterationStatements.qml"_s;
|
||||
DomItem rootQmlObject = rootQmlObjectFromFile(testFile, qmltypeDirs);
|
||||
|
||||
QVERIFY(rootQmlObject);
|
||||
DomItem methods = rootQmlObject.methods();
|
||||
QVERIFY(methods);
|
||||
|
||||
{
|
||||
// while statement
|
||||
DomItem whileTest = methods.key("whileStatement")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements)
|
||||
.index(1);
|
||||
QVERIFY(whileTest);
|
||||
QCOMPARE(whileTest.internalKind(), DomType::ScriptWhileStatement);
|
||||
auto whileScope = whileTest.semanticScope();
|
||||
QVERIFY(whileScope);
|
||||
QVERIFY(*whileScope);
|
||||
DomItem whileBody = whileTest.field(Fields::body);
|
||||
QVERIFY(whileBody);
|
||||
QCOMPARE(whileBody.internalKind(), DomType::ScriptBlockStatement);
|
||||
auto scope = whileBody.semanticScope();
|
||||
QVERIFY(scope);
|
||||
QVERIFY(*scope);
|
||||
QCOMPARE(whileBody.field(Fields::statements).index(0).internalKind(),
|
||||
DomType::ScriptBinaryExpression); // i = i - 1
|
||||
QCOMPARE(
|
||||
whileBody.field(Fields::statements).index(0).field(Fields::left).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(whileBody.field(Fields::statements)
|
||||
.index(0)
|
||||
.field(Fields::left)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
u"i");
|
||||
DomItem whileExpression = whileTest.field(Fields::expression);
|
||||
QVERIFY(whileExpression);
|
||||
QCOMPARE(whileExpression.internalKind(), DomType::ScriptBinaryExpression); // i > 0
|
||||
QCOMPARE(whileExpression.field(Fields::left).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(whileExpression.field(Fields::left)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
u"i");
|
||||
QCOMPARE(whileExpression.field(Fields::right).internalKind(), DomType::ScriptLiteral);
|
||||
QCOMPARE(whileExpression.field(Fields::right)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toInteger(),
|
||||
0);
|
||||
|
||||
DomItem singleLineWhile = methods.key("whileStatement")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements)
|
||||
.index(2);
|
||||
QVERIFY(singleLineWhile);
|
||||
QCOMPARE(singleLineWhile.internalKind(), DomType::ScriptWhileStatement);
|
||||
DomItem singleLineWhileBody = singleLineWhile.field(Fields::body);
|
||||
QVERIFY(singleLineWhileBody);
|
||||
QCOMPARE(singleLineWhileBody.internalKind(), DomType::ScriptBinaryExpression);
|
||||
auto singleLineWhileScope = singleLineWhile.semanticScope();
|
||||
QVERIFY(singleLineWhileScope);
|
||||
QVERIFY(*singleLineWhileScope);
|
||||
QVERIFY(singleLineWhileScope.value()->findJSIdentifier(
|
||||
"i")); // i is in the parent scope
|
||||
}
|
||||
|
||||
{
|
||||
// do-while statement
|
||||
DomItem doWhile = methods.key("doWhile")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements)
|
||||
.index(1);
|
||||
QVERIFY(doWhile);
|
||||
QCOMPARE(doWhile.internalKind(), DomType::ScriptDoWhileStatement);
|
||||
|
||||
auto doWhileScope = doWhile.semanticScope();
|
||||
QVERIFY(doWhileScope);
|
||||
QVERIFY(*doWhileScope);
|
||||
DomItem doWhileBody = doWhile.field(Fields::body);
|
||||
QVERIFY(doWhileBody);
|
||||
auto doWhileBodyScope = doWhileBody.semanticScope();
|
||||
QVERIFY(doWhileBodyScope);
|
||||
QVERIFY(*doWhileBodyScope);
|
||||
QVERIFY(doWhileBodyScope.value()->JSIdentifier("b")); // const b = a
|
||||
QCOMPARE(doWhileBody.internalKind(), DomType::ScriptBlockStatement);
|
||||
QCOMPARE(doWhileBody.field(Fields::statements).index(0).internalKind(),
|
||||
DomType::ScriptVariableDeclaration); // const b = a
|
||||
QCOMPARE(doWhileBody.field(Fields::statements).index(1).internalKind(),
|
||||
DomType::ScriptBinaryExpression); // a = a - 1
|
||||
|
||||
DomItem doWhileExpression = doWhile.field(Fields::expression);
|
||||
QVERIFY(doWhileExpression);
|
||||
QCOMPARE(doWhileExpression.internalKind(), DomType::ScriptBinaryExpression); // a > 0
|
||||
QCOMPARE(doWhileExpression.field(Fields::left).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(doWhileExpression.field(Fields::left)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
u"a");
|
||||
QCOMPARE(doWhileExpression.field(Fields::right).internalKind(), DomType::ScriptLiteral);
|
||||
QCOMPARE(doWhileExpression.field(Fields::right)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toInteger(),
|
||||
0);
|
||||
DomItem singleDoWhile = methods.key("doWhile")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements)
|
||||
.index(2);
|
||||
auto singleDoWhileScope = singleDoWhile.semanticScope();
|
||||
QVERIFY(singleDoWhileScope);
|
||||
QVERIFY(*singleDoWhileScope);
|
||||
QVERIFY(singleDoWhileScope.value()->findJSIdentifier("a")); // a = a - 1
|
||||
}
|
||||
|
||||
{
|
||||
// for..of
|
||||
DomItem statements = methods.key("forOf")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements);
|
||||
QVERIFY(statements);
|
||||
QCOMPARE(statements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
|
||||
DomItem outerForEach = statements.index(1);
|
||||
QVERIFY(outerForEach);
|
||||
QCOMPARE(outerForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
DomItem bindingElements =
|
||||
outerForEach.field(Fields::bindingElement).field(Fields::bindingElement);
|
||||
QVERIFY(bindingElements);
|
||||
QCOMPARE(bindingElements.internalKind(), DomType::ScriptArray);
|
||||
QCOMPARE(bindingElements.field(Fields::elements).length(), 2);
|
||||
QCOMPARE(bindingElements.field(Fields::elements)
|
||||
.index(1)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"b");
|
||||
QCOMPARE(outerForEach.field(Fields::expression).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(outerForEach.field(Fields::expression)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
u"iterable");
|
||||
DomItem forEachStatements = outerForEach.field(Fields::body).field(Fields::statements);
|
||||
QCOMPARE(forEachStatements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
|
||||
QCOMPARE(forEachStatements.index(1).internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(forEachStatements.index(2).internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(forEachStatements.index(3).internalKind(), DomType::ScriptForEachStatement);
|
||||
DomItem firstForEach = forEachStatements.index(1);
|
||||
QVERIFY(firstForEach);
|
||||
DomItem bindingElement =
|
||||
firstForEach.field(Fields::bindingElement).field(Fields::bindingElement);
|
||||
QCOMPARE(bindingElement.internalKind(), DomType::ScriptArray);
|
||||
|
||||
QCOMPARE(bindingElement.field(Fields::elements).length(), 4);
|
||||
QCOMPARE(bindingElement.field(Fields::elements)
|
||||
.index(0)
|
||||
.field(Fields::identifier)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"a1");
|
||||
DomItem secondForEach = forEachStatements.index(2);
|
||||
QCOMPARE(secondForEach.field(Fields::bindingElement).internalKind(),
|
||||
DomType::ScriptPattern);
|
||||
QCOMPARE(secondForEach.field(Fields::bindingElement)
|
||||
.field(Fields::identifier)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"k");
|
||||
QCOMPARE(secondForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(secondForEach.field(Fields::expression).internalKind(), DomType::ScriptArray);
|
||||
QVERIFY(secondForEach.field(Fields::body));
|
||||
QCOMPARE(secondForEach.field(Fields::body).internalKind(),
|
||||
DomType::ScriptBlockStatement);
|
||||
DomItem thirdForEach = forEachStatements.index(3);
|
||||
QCOMPARE(thirdForEach.field(Fields::bindingElement).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(thirdForEach.field(Fields::bindingElement).value().toString(), "t");
|
||||
|
||||
QCOMPARE(thirdForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(thirdForEach.field(Fields::expression).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(thirdForEach.field(Fields::expression)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
u"a");
|
||||
QVERIFY(thirdForEach.field(Fields::body));
|
||||
QCOMPARE(thirdForEach.field(Fields::body).internalKind(),
|
||||
DomType::ScriptBlockStatement);
|
||||
|
||||
DomItem forthForEach = forEachStatements.index(3);
|
||||
QVERIFY(forthForEach);
|
||||
auto forthForEachScope = forthForEach.semanticScope();
|
||||
QVERIFY(forthForEachScope);
|
||||
QVERIFY(*forthForEachScope);
|
||||
QVERIFY(forthForEachScope.value()->findJSIdentifier("t")); // t lives in parent scope
|
||||
}
|
||||
|
||||
{
|
||||
// for..in
|
||||
DomItem statements = methods.key("forIn")
|
||||
.index(0)
|
||||
.field(Fields::body)
|
||||
.field(Fields::scriptElement)
|
||||
.field(Fields::statements);
|
||||
QVERIFY(statements);
|
||||
QCOMPARE(statements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
|
||||
DomItem outerForEach = statements.index(1);
|
||||
QVERIFY(outerForEach);
|
||||
auto outerForEachScope = outerForEach.semanticScope();
|
||||
QVERIFY(outerForEachScope);
|
||||
QVERIFY(*outerForEachScope);
|
||||
QVERIFY(outerForEachScope.value()->findJSIdentifier("a")); // var [a,b,c,d]
|
||||
QVERIFY(outerForEachScope.value()->findJSIdentifier("b"));
|
||||
QVERIFY(outerForEachScope.value()->findJSIdentifier("c"));
|
||||
QVERIFY(outerForEachScope.value()->findJSIdentifier("d"));
|
||||
QCOMPARE(outerForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(statements.index(1).internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(outerForEach.field(Fields::expression)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"enumerable");
|
||||
auto outerForEachBodyScope = outerForEach.field(Fields::body).semanticScope();
|
||||
QVERIFY(outerForEachBodyScope);
|
||||
QVERIFY(*outerForEachBodyScope);
|
||||
QVERIFY(outerForEachBodyScope.value()->JSIdentifier("t")); // let t
|
||||
DomItem forInStatements = outerForEach.field(Fields::body).field(Fields::statements);
|
||||
QCOMPARE(forInStatements.index(0).internalKind(), DomType::ScriptVariableDeclaration);
|
||||
QCOMPARE(forInStatements.index(1).internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(forInStatements.index(2).internalKind(), DomType::ScriptForEachStatement);
|
||||
DomItem firstForEach = forInStatements.index(1);
|
||||
QVERIFY(firstForEach);
|
||||
auto firstForEachScope = firstForEach.semanticScope();
|
||||
QVERIFY(firstForEachScope);
|
||||
QVERIFY(*firstForEachScope);
|
||||
QVERIFY(firstForEachScope.value()->findJSIdentifier("t"));
|
||||
QCOMPARE(firstForEach.field(Fields::bindingElement).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(firstForEach.field(Fields::bindingElement)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"t");
|
||||
QCOMPARE(firstForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(firstForEach.field(Fields::expression).internalKind(),
|
||||
DomType::ScriptIdentifierExpression);
|
||||
QCOMPARE(firstForEach.field(Fields::expression)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"enumerable");
|
||||
QVERIFY(firstForEach.field(Fields::body));
|
||||
QCOMPARE(firstForEach.field(Fields::body).internalKind(),
|
||||
DomType::ScriptBlockStatement);
|
||||
|
||||
DomItem secondForEach = forInStatements.index(2);
|
||||
QVERIFY(secondForEach);
|
||||
auto secondForEachScope = secondForEach.semanticScope();
|
||||
QVERIFY(secondForEachScope);
|
||||
QVERIFY(*secondForEachScope);
|
||||
QVERIFY(secondForEachScope.value()->JSIdentifier("a1")); // const [a1,,a2,...rest]
|
||||
QVERIFY(secondForEachScope.value()->JSIdentifier("a2"));
|
||||
QVERIFY(secondForEachScope.value()->JSIdentifier("rest"));
|
||||
|
||||
DomItem bindingElement =
|
||||
secondForEach.field(Fields::bindingElement).field(Fields::bindingElement);
|
||||
QCOMPARE(bindingElement.internalKind(), DomType::ScriptArray);
|
||||
QCOMPARE(bindingElement.field(Fields::elements)
|
||||
.index(3)
|
||||
.field(Fields::identifier)
|
||||
.field(Fields::identifier)
|
||||
.value()
|
||||
.toString(),
|
||||
"rest");
|
||||
QCOMPARE(secondForEach.internalKind(), DomType::ScriptForEachStatement);
|
||||
QCOMPARE(secondForEach.field(Fields::expression).internalKind(),
|
||||
DomType::ScriptBinaryExpression);
|
||||
QVERIFY(secondForEach.field(Fields::body));
|
||||
QCOMPARE(secondForEach.field(Fields::body).internalKind(),
|
||||
DomType::ScriptBlockStatement);
|
||||
DomItem thirdForEach = forInStatements.index(3);
|
||||
QVERIFY(thirdForEach);
|
||||
auto thirdForEachScope = thirdForEach.semanticScope();
|
||||
QVERIFY(thirdForEachScope);
|
||||
QVERIFY(*thirdForEachScope);
|
||||
QVERIFY(thirdForEachScope.value()->JSIdentifier("t"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct DomItemWithLocation
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue