QmlJS: Update QML parser using the one from qtdeclarative 5.15

We need to do this because the new "required" keyword should be
recognized by Qt Creator.

This is not a verbatim copy of the QML parser from qtdeclarative. A few
data structures have changed that would require large scale changes in
otherwise unrelated parts of the code. For example, all Visitors need to
handle recursion depth errors now and the DiagnosticMessage only has
line and column now, no longer begin and legth.

Change-Id: Iea5b04e27b07e0cba55d64b844315af9828acbf7
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Ulf Hermann
2019-10-04 16:11:02 +02:00
parent 979d14525c
commit 58d35f8a64
14 changed files with 4344 additions and 3513 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -51,21 +51,6 @@ ClassExpression *asAnonymousClassDefinition(Node *n)
return c;
}
void Node::accept(Visitor *visitor)
{
if (visitor->preVisit(this)) {
accept0(visitor);
}
visitor->postVisit(this);
}
void Node::accept(Node *node, Visitor *visitor)
{
if (node)
node->accept(visitor);
}
ExpressionNode *Node::expressionCast()
{
return nullptr;
@@ -106,6 +91,12 @@ ClassExpression *Node::asClassDefinition()
return nullptr;
}
bool Node::ignoreRecursionDepth() const
{
static const bool doIgnore = qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW");
return doIgnore;
}
ExpressionNode *ExpressionNode::expressionCast()
{
return this;
@@ -132,7 +123,7 @@ FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *po
}
AST::PatternElement *binding = nullptr;
if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
binding = new (pool) AST::PatternElement(idExpr->name, rhs);
binding = new (pool) AST::PatternElement(idExpr->name, /*type annotation*/nullptr, rhs);
binding->identifierToken = idExpr->identifierToken;
} else if (AST::Pattern *p = expr->patternCast()) {
SourceLocation loc;
@@ -239,12 +230,11 @@ void StringLiteral::accept0(Visitor *visitor)
void TemplateLiteral::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
if (next)
accept(next, visitor);
bool accepted = true;
for (TemplateLiteral *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
visitor->endVisit(it);
}
visitor->endVisit(this);
}
void NumericLiteral::accept0(Visitor *visitor)
@@ -451,6 +441,8 @@ bool PatternProperty::convertLiteralToAssignmentPattern(MemoryPool *pool, Source
*errorMessage = QString::fromLatin1("Invalid getter/setter in destructuring expression.");
return false;
}
if (type == Method)
type = Literal;
Q_ASSERT(type == Literal);
return PatternElement::convertLiteralToAssignmentPattern(pool, errorLocation, errorMessage);
}
@@ -960,6 +952,7 @@ void FunctionDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
accept(typeAnnotation, visitor);
accept(body, visitor);
}
@@ -970,6 +963,7 @@ void FunctionExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
accept(typeAnnotation, visitor);
accept(body, visitor);
}
@@ -981,9 +975,9 @@ FunctionExpression *FunctionExpression::asFunctionDefinition()
return this;
}
QStringList FormalParameterList::formals() const
BoundNames FormalParameterList::formals() const
{
QStringList formals;
BoundNames formals;
int i = 0;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element) {
@@ -991,18 +985,18 @@ QStringList FormalParameterList::formals() const
int duplicateIndex = formals.indexOf(name);
if (duplicateIndex >= 0) {
// change the name of the earlier argument to enforce the lookup semantics from the spec
formals[duplicateIndex] += QLatin1String("#") + QString::number(i);
formals[duplicateIndex].id += QLatin1String("#") + QString::number(i);
}
formals += name;
formals += {name, it->element->typeAnnotation};
}
++i;
}
return formals;
}
QStringList FormalParameterList::boundNames() const
BoundNames FormalParameterList::boundNames() const
{
QStringList names;
BoundNames names;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element)
it->element->boundNames(&names);
@@ -1012,13 +1006,13 @@ QStringList FormalParameterList::boundNames() const
void FormalParameterList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(element, visitor);
if (next)
accept(next, visitor);
bool accepted = true;
for (FormalParameterList *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
if (accepted)
accept(it->element, visitor);
visitor->endVisit(it);
}
visitor->endVisit(this);
}
FormalParameterList *FormalParameterList::finish(QmlJS::MemoryPool *pool)
@@ -1270,6 +1264,35 @@ void UiQualifiedId::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void Type::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(typeId, visitor);
accept(typeArguments, visitor);
}
visitor->endVisit(this);
}
void TypeArgumentList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (TypeArgumentList *it = this; it; it = it->next)
accept(it->typeId, visitor);
}
visitor->endVisit(this);
}
void TypeAnnotation::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(type, visitor);
}
visitor->endVisit(this);
}
void UiImport::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@@ -1289,12 +1312,14 @@ void UiPragma::accept0(Visitor *visitor)
void UiHeaderItemList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(headerItem, visitor);
accept(next, visitor);
}
bool accepted = true;
for (UiHeaderItemList *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
if (accepted)
accept(it->headerItem, visitor);
visitor->endVisit(this);
visitor->endVisit(it);
}
}
@@ -1338,13 +1363,14 @@ void PatternElement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(bindingTarget, visitor);
accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternElement::boundNames(QStringList *names)
void PatternElement::boundNames(BoundNames *names)
{
if (bindingTarget) {
if (PatternElementList *e = elementList())
@@ -1352,23 +1378,24 @@ void PatternElement::boundNames(QStringList *names)
else if (PatternPropertyList *p = propertyList())
p->boundNames(names);
} else {
names->append(bindingIdentifier.toString());
names->append({bindingIdentifier.toString(), typeAnnotation});
}
}
void PatternElementList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(elision, visitor);
accept(element, visitor);
if (next)
accept(next, visitor);
bool accepted = true;
for (PatternElementList *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
if (accepted) {
accept(it->elision, visitor);
accept(it->element, visitor);
}
visitor->endVisit(it);
}
visitor->endVisit(this);
}
void PatternElementList::boundNames(QStringList *names)
void PatternElementList::boundNames(BoundNames *names)
{
for (PatternElementList *it = this; it; it = it->next) {
if (it->element)
@@ -1381,29 +1408,30 @@ void PatternProperty::accept0(Visitor *visitor)
if (visitor->visit(this)) {
accept(name, visitor);
accept(bindingTarget, visitor);
accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternProperty::boundNames(QStringList *names)
void PatternProperty::boundNames(BoundNames *names)
{
PatternElement::boundNames(names);
}
void PatternPropertyList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(property, visitor);
if (next)
accept(next, visitor);
bool accepted = true;
for (PatternPropertyList *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
if (accepted)
accept(it->property, visitor);
visitor->endVisit(it);
}
visitor->endVisit(this);
}
void PatternPropertyList::boundNames(QStringList *names)
void PatternPropertyList::boundNames(BoundNames *names)
{
for (PatternPropertyList *it = this; it; it = it->next)
it->property->boundNames(names);
@@ -1445,13 +1473,14 @@ void ClassDeclaration::accept0(Visitor *visitor)
void ClassElementList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(property, visitor);
if (next)
accept(next, visitor);
}
bool accepted = true;
for (ClassElementList *it = this; it && accepted; it = it->next) {
accepted = visitor->visit(it);
if (accepted)
accept(it->property, visitor);
visitor->endVisit(this);
visitor->endVisit(it);
}
}
ClassElementList *ClassElementList::finish()
@@ -1471,6 +1500,37 @@ LeftHandSideExpression *LeftHandSideExpression::leftHandSideExpressionCast()
return this;
}
void UiVersionSpecifier::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
QString Type::toString() const
{
QString result;
toString(&result);
return result;
}
void Type::toString(QString *out) const
{
for (QmlJS::AST::UiQualifiedId *it = typeId; it; it = it->next) {
out->append(it->name);
if (it->next)
out->append(QLatin1Char('.'));
}
if (typeArguments) {
out->append(QLatin1Char('<'));
if (auto subType = static_cast<TypeArgumentList*>(typeArguments)->typeId)
subType->toString(out);
out->append(QLatin1Char('>'));
};
}
} } // namespace QmlJS::AST
QT_QML_END_NAMESPACE

View File

@@ -218,7 +218,9 @@ public:
Kind_PatternElementList,
Kind_PatternProperty,
Kind_PatternPropertyList,
Kind_Type,
Kind_TypeArgumentList,
Kind_TypeAnnotation,
Kind_UiArrayBinding,
Kind_UiImport,
@@ -236,7 +238,8 @@ public:
Kind_UiSourceElement,
Kind_UiHeaderItemList,
Kind_UiEnumDeclaration,
Kind_UiEnumMemberList
Kind_UiEnumMemberList,
Kind_UiVersionSpecifier
};
inline Node() {}
@@ -256,11 +259,35 @@ public:
virtual FunctionExpression *asFunctionDefinition();
virtual ClassExpression *asClassDefinition();
void accept(Visitor *visitor);
static void accept(Node *node, Visitor *visitor);
bool ignoreRecursionDepth() const;
inline void accept(Visitor *visitor)
{
Visitor::RecursionDepthCheck recursionCheck(visitor);
// Stack overflow is uncommon, ignoreRecursionDepth() only returns true if
// QV4_CRASH_ON_STACKOVERFLOW is set, and ignoreRecursionDepth() needs to be out of line.
// Therefore, check for ignoreRecursionDepth() _after_ calling the inline recursionCheck().
if (recursionCheck() || ignoreRecursionDepth()) {
if (visitor->preVisit(this))
accept0(visitor);
visitor->postVisit(this);
} else {
visitor->throwRecursionDepthError();
}
}
inline static void accept(Node *node, Visitor *visitor)
{
if (node)
node->accept(visitor);
}
// ### Remove when we can. This is part of the qmldevtools library, though.
inline static void acceptChild(Node *node, Visitor *visitor)
{ return accept(node, visitor); } // ### remove
{
return accept(node, visitor);
}
virtual void accept0(Visitor *visitor) = 0;
virtual SourceLocation firstSourceLocation() const = 0;
@@ -270,6 +297,139 @@ public:
int kind = Kind_Undefined;
};
template<typename T>
T lastListElement(T head)
{
auto current = head;
while (current->next)
current = current->next;
return current;
}
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
public:
QMLJS_DECLARE_AST_NODE(UiQualifiedId)
UiQualifiedId(const QStringRef &name)
: next(this), name(name)
{ kind = K; }
UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
: name(name)
{
kind = K;
next = previous->next;
previous->next = this;
}
UiQualifiedId *finish()
{
UiQualifiedId *head = next;
next = nullptr;
return head;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
{ return lastListElement(this)->identifierToken; }
// attributes
UiQualifiedId *next;
QStringRef name;
SourceLocation identifierToken;
};
class QML_PARSER_EXPORT Type: public Node
{
public:
QMLJS_DECLARE_AST_NODE(Type)
Type(UiQualifiedId *typeId, Node *typeArguments = nullptr)
: typeId(typeId)
, typeArguments(typeArguments)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return typeArguments ? typeArguments->lastSourceLocation() : typeId->lastSourceLocation(); }
QString toString() const;
void toString(QString *out) const;
// attributes
UiQualifiedId *typeId;
Node *typeArguments; // TypeArgumentList
};
class QML_PARSER_EXPORT TypeArgumentList: public Node
{
public:
QMLJS_DECLARE_AST_NODE(TypeArgumentList)
TypeArgumentList(Type *typeId)
: typeId(typeId)
, next(nullptr)
{ kind = K; }
TypeArgumentList(TypeArgumentList *previous, Type *typeId)
: typeId(typeId)
{
kind = K;
next = previous->next;
previous->next = this;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return lastListElement(this)->typeId->lastSourceLocation(); }
inline TypeArgumentList *finish()
{
TypeArgumentList *front = next;
next = nullptr;
return front;
}
// attributes
Type *typeId;
TypeArgumentList *next;
};
class QML_PARSER_EXPORT TypeAnnotation: public Node
{
public:
QMLJS_DECLARE_AST_NODE(TypeAnnotation)
TypeAnnotation(Type *type)
: type(type)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return colonToken; }
SourceLocation lastSourceLocation() const override
{ return type->lastSourceLocation(); }
// attributes
Type *type;
SourceLocation colonToken;
};
class QML_PARSER_EXPORT ExpressionNode: public Node
{
public:
@@ -459,7 +619,30 @@ public:
SourceLocation literalToken;
};
class QML_PARSER_EXPORT StringLiteral: public LeftHandSideExpression
class QML_PARSER_EXPORT UiVersionSpecifier : public Node
{
public:
QMLJS_DECLARE_AST_NODE(UiVersionSpecifier)
UiVersionSpecifier(int majorum, int minorum) : majorVersion(majorum), minorVersion(minorum) { kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override { return majorToken; }
SourceLocation lastSourceLocation() const override
{
return minorToken.isValid() ? minorToken : majorToken;
}
// attributes:
int majorVersion;
int minorVersion;
SourceLocation majorToken;
SourceLocation minorToken;
};
class QML_PARSER_EXPORT StringLiteral : public LeftHandSideExpression
{
public:
QMLJS_DECLARE_AST_NODE(StringLiteral)
@@ -485,19 +668,23 @@ class QML_PARSER_EXPORT TemplateLiteral : public LeftHandSideExpression
public:
QMLJS_DECLARE_AST_NODE(TemplateLiteral)
TemplateLiteral(const QStringRef &str, ExpressionNode *e)
: value(str), expression(e), next(nullptr)
TemplateLiteral(const QStringRef &str, const QStringRef &raw, ExpressionNode *e)
: value(str), rawValue(raw), expression(e), next(nullptr)
{ kind = K; }
SourceLocation firstSourceLocation() const override
{ return literalToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : (expression ? expression->lastSourceLocation() : literalToken); }
{
auto last = lastListElement(this);
return (last->expression ? last->expression->lastSourceLocation() : last->literalToken);
}
void accept0(Visitor *visitor) override;
QStringRef value;
QStringRef rawValue;
ExpressionNode *expression;
TemplateLiteral *next;
SourceLocation literalToken;
@@ -614,7 +801,7 @@ public:
{ return commaToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : commaToken; }
{ return lastListElement(this)->commaToken; }
inline Elision *finish ()
{
@@ -647,6 +834,34 @@ public:
SourceLocation propertyNameToken;
};
struct QML_PARSER_EXPORT BoundName
{
QString id;
TypeAnnotation *typeAnnotation = nullptr;
BoundName(const QString &id, TypeAnnotation *typeAnnotation)
: id(id), typeAnnotation(typeAnnotation)
{}
BoundName() = default;
QString typeName() const { return typeAnnotation ? typeAnnotation->type->toString() : QString(); }
};
struct BoundNames : public QVector<BoundName>
{
int indexOf(const QString &name, int from = 0) const
{
auto found = std::find_if(constBegin() + from, constEnd(),
[name](const BoundName &it) { return it.id == name; });
if (found == constEnd())
return -1;
return found - constBegin();
}
bool contains(const QString &name) const
{
return indexOf(name) != -1;
}
};
class QML_PARSER_EXPORT PatternElement : public Node
{
public:
@@ -655,6 +870,7 @@ public:
enum Type {
// object literal types
Literal,
Method,
Getter,
Setter,
@@ -670,8 +886,9 @@ public:
: initializer(i), type(t)
{ kind = K; }
PatternElement(const QStringRef &n, ExpressionNode *i = nullptr, Type t = Binding)
PatternElement(const QStringRef &n, TypeAnnotation *typeAnnotation = nullptr, ExpressionNode *i = nullptr, Type t = Binding)
: bindingIdentifier(n), initializer(i), type(t)
, typeAnnotation(typeAnnotation)
{
Q_ASSERT(t >= RestElement);
kind = K;
@@ -691,7 +908,7 @@ public:
{ return identifierToken.isValid() ? identifierToken : (bindingTarget ? bindingTarget->firstSourceLocation() : initializer->firstSourceLocation()); }
SourceLocation lastSourceLocation() const override
{ return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : identifierToken); }
{ return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : (typeAnnotation ? typeAnnotation->lastSourceLocation() : identifierToken)); }
ExpressionNode *destructuringTarget() const { return bindingTarget; }
Pattern *destructuringPattern() const { return bindingTarget ? bindingTarget->patternCast() : nullptr; }
@@ -701,7 +918,7 @@ public:
bool isVariableDeclaration() const { return scope != VariableScope::NoScope; }
bool isLexicallyScoped() const { return scope == VariableScope::Let || scope == VariableScope::Const; }
virtual void boundNames(QStringList *names);
virtual void boundNames(BoundNames *names);
// attributes
SourceLocation identifierToken;
@@ -709,6 +926,7 @@ public:
ExpressionNode *bindingTarget = nullptr;
ExpressionNode *initializer = nullptr;
Type type = Literal;
TypeAnnotation *typeAnnotation = nullptr;
// when used in a VariableDeclarationList
VariableScope scope = VariableScope::NoScope;
bool isForDeclaration = false;
@@ -738,13 +956,16 @@ public:
void accept0(Visitor *visitor) override;
void boundNames(QStringList *names);
void boundNames(BoundNames *names);
SourceLocation firstSourceLocation() const override
{ return elision ? elision->firstSourceLocation() : element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : (element ? element->lastSourceLocation() : elision->lastSourceLocation()); }
{
auto last = lastListElement(this);
return last->element ? last->element->lastSourceLocation() : last->elision->lastSourceLocation();
}
Elision *elision = nullptr;
PatternElement *element = nullptr;
@@ -761,7 +982,7 @@ public:
{ kind = K; }
PatternProperty(PropertyName *name, const QStringRef &n, ExpressionNode *i = nullptr)
: PatternElement(n, i), name(name)
: PatternElement(n, /*type annotation*/nullptr, i), name(name)
{ kind = K; }
PatternProperty(PropertyName *name, Pattern *pattern, ExpressionNode *i = nullptr)
@@ -778,7 +999,7 @@ public:
return loc.isValid() ? loc : name->lastSourceLocation();
}
void boundNames(QStringList *names) override;
void boundNames(BoundNames *names) override;
bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) override;
// attributes
@@ -806,7 +1027,7 @@ public:
void accept0(Visitor *visitor) override;
void boundNames(QStringList *names);
void boundNames(BoundNames *names);
inline PatternPropertyList *finish ()
{
@@ -819,7 +1040,7 @@ public:
{ return property->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : property->lastSourceLocation(); }
{ return lastListElement(this)->property->lastSourceLocation(); }
PatternProperty *property;
PatternPropertyList *next;
@@ -1428,7 +1649,9 @@ public:
{ return statement->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : statement->lastSourceLocation(); }
{
return lastListElement(this)->statement->lastSourceLocation();
}
inline StatementList *finish ()
{
@@ -1543,7 +1766,7 @@ public:
{ return expression->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return semicolonToken.isValid() ? semicolonToken : expression->lastSourceLocation(); }
{ return expression->lastSourceLocation(); }
// attributes
ExpressionNode *expression;
@@ -1921,7 +2144,9 @@ public:
{ return clause->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : clause->lastSourceLocation(); }
{
return lastListElement(this)->clause->lastSourceLocation();
}
inline CaseClauses *finish ()
{
@@ -2096,8 +2321,9 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode
public:
QMLJS_DECLARE_AST_NODE(FunctionExpression)
FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b):
name (n), formals (f), body (b)
FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
name (n), formals (f), body (b),
typeAnnotation(typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@@ -2116,6 +2342,7 @@ public:
bool isGenerator = false;
FormalParameterList *formals;
StatementList *body;
TypeAnnotation *typeAnnotation;
SourceLocation functionToken;
SourceLocation identifierToken;
SourceLocation lparenToken;
@@ -2129,8 +2356,8 @@ class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression
public:
QMLJS_DECLARE_AST_NODE(FunctionDeclaration)
FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b):
FunctionExpression(n, f, b)
FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
FunctionExpression(n, f, b, typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@@ -2200,9 +2427,9 @@ public:
return false;
}
QStringList formals() const;
BoundNames formals() const;
QStringList boundNames() const;
BoundNames boundNames() const;
void accept0(Visitor *visitor) override;
@@ -2210,7 +2437,9 @@ public:
{ return element->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : element->lastSourceLocation(); }
{
return lastListElement(this)->element->lastSourceLocation();
}
FormalParameterList *finish(MemoryPool *pool);
@@ -2387,7 +2616,9 @@ public:
{ return importSpecifierToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : importSpecifierToken; }
{
return lastListElement(this)->importSpecifierToken;
}
// attributes
SourceLocation importSpecifierToken;
@@ -2624,7 +2855,7 @@ public:
SourceLocation firstSourceLocation() const override
{ return exportSpecifier->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : exportSpecifier->lastSourceLocation(); }
{ return lastListElement(this)->exportSpecifier->lastSourceLocation(); }
// attributes
ExportSpecifier *exportSpecifier;
@@ -2751,44 +2982,6 @@ public:
SourceLocation semicolonToken;
};
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
public:
QMLJS_DECLARE_AST_NODE(UiQualifiedId)
UiQualifiedId(const QStringRef &name)
: next(this), name(name)
{ kind = K; }
UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
: name(name)
{
kind = K;
next = previous->next;
previous->next = this;
}
UiQualifiedId *finish()
{
UiQualifiedId *head = next;
next = nullptr;
return head;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : identifierToken; }
// attributes
UiQualifiedId *next;
QStringRef name;
SourceLocation identifierToken;
};
class QML_PARSER_EXPORT UiImport: public Node
{
public:
@@ -2820,6 +3013,7 @@ public:
SourceLocation asToken;
SourceLocation importIdToken;
SourceLocation semicolonToken;
UiVersionSpecifier *version = nullptr;
};
class QML_PARSER_EXPORT UiObjectMember: public Node
@@ -2854,7 +3048,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
{ return lastListElement(this)->member->lastSourceLocation(); }
UiObjectMemberList *finish()
{
@@ -2933,7 +3127,7 @@ public:
{ return headerItem->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : headerItem->lastSourceLocation(); }
{ return lastListElement(this)->headerItem->lastSourceLocation(); }
// attributes
Node *headerItem;
@@ -2997,7 +3191,7 @@ public:
{ return member->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : member->lastSourceLocation(); }
{ return lastListElement(this)->member->lastSourceLocation(); }
UiArrayMemberList *finish()
{
@@ -3055,10 +3249,13 @@ public:
void accept0(Visitor *) override;
SourceLocation firstSourceLocation() const override
{ return propertyTypeToken; }
{ return colonToken.isValid() ? identifierToken : propertyTypeToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : identifierToken; }
{
auto last = lastListElement(this);
return (last->colonToken.isValid() ? last->propertyTypeToken : last->identifierToken);
}
inline UiParameterList *finish ()
{
@@ -3074,6 +3271,7 @@ public:
SourceLocation commaToken;
SourceLocation propertyTypeToken;
SourceLocation identifierToken;
SourceLocation colonToken;
};
class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember
@@ -3100,6 +3298,8 @@ public:
return defaultToken;
else if (readonlyToken.isValid())
return readonlyToken;
else if (requiredToken.isValid())
return requiredToken;
return propertyToken;
}
@@ -3123,10 +3323,13 @@ public:
UiObjectMember *binding; // initialized with a QML object or array.
bool isDefaultMember;
bool isReadonlyMember;
bool isRequired = false;
UiParameterList *parameters;
// TODO: merge source locations
SourceLocation defaultToken;
SourceLocation readonlyToken;
SourceLocation propertyToken;
SourceLocation requiredToken;
SourceLocation typeModifierToken;
SourceLocation typeToken;
SourceLocation identifierToken;
@@ -3168,7 +3371,7 @@ public:
SourceLocation firstSourceLocation() const override
{
if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
if (FunctionExpression *funDecl = sourceElement->asFunctionDefinition())
return funDecl->firstSourceLocation();
else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
return varStmt->firstSourceLocation();
@@ -3178,7 +3381,7 @@ public:
SourceLocation lastSourceLocation() const override
{
if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
if (FunctionExpression *funDecl = sourceElement->asFunctionDefinition())
return funDecl->lastSourceLocation();
else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
return varStmt->lastSourceLocation();
@@ -3310,8 +3513,10 @@ public:
{ return memberToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() :
valueToken.isValid() ? valueToken : memberToken; }
{
auto last = lastListElement(this);
return last->valueToken.isValid() ? last->valueToken : last->memberToken;
}
void accept0(Visitor *visitor) override;

View File

@@ -163,6 +163,9 @@ class NestedExpression;
class ClassExpression;
class ClassDeclaration;
class ClassElementList;
class TypeArgumentList;
class Type;
class TypeAnnotation;
// ui elements
class UiProgram;
@@ -183,6 +186,7 @@ class UiQualifiedId;
class UiHeaderItemList;
class UiEnumDeclaration;
class UiEnumMemberList;
class UiVersionSpecifier;
} } // namespace AST

View File

@@ -29,7 +29,7 @@ QT_QML_BEGIN_NAMESPACE
namespace QmlJS { namespace AST {
Visitor::Visitor()
Visitor::Visitor(quint16 parentRecursionDepth) : m_recursionDepth(parentRecursionDepth)
{
}

View File

@@ -46,7 +46,33 @@ namespace QmlJS { namespace AST {
class QML_PARSER_EXPORT Visitor
{
public:
Visitor();
class RecursionDepthCheck
{
Q_DISABLE_COPY(RecursionDepthCheck)
public:
RecursionDepthCheck(RecursionDepthCheck &&) = delete;
RecursionDepthCheck &operator=(RecursionDepthCheck &&) = delete;
RecursionDepthCheck(Visitor *visitor) : m_visitor(visitor)
{
++(m_visitor->m_recursionDepth);
}
~RecursionDepthCheck()
{
--(m_visitor->m_recursionDepth);
}
bool operator()() const {
return m_visitor->m_recursionDepth < s_recursionLimit;
}
private:
static const quint16 s_recursionLimit = 4096;
Visitor *m_visitor;
};
Visitor(quint16 parentRecursionDepth = 0);
virtual ~Visitor();
virtual bool preVisit(Node *) { return true; }
@@ -70,6 +96,7 @@ public:
virtual bool visit(UiQualifiedId *) { return true; }
virtual bool visit(UiEnumDeclaration *) { return true; }
virtual bool visit(UiEnumMemberList *) { return true; }
virtual bool visit(UiVersionSpecifier *) { return true; }
virtual void endVisit(UiProgram *) {}
virtual void endVisit(UiImport *) {}
@@ -88,6 +115,7 @@ public:
virtual void endVisit(UiQualifiedId *) {}
virtual void endVisit(UiEnumDeclaration *) {}
virtual void endVisit(UiEnumMemberList *) { }
virtual void endVisit(UiVersionSpecifier *) {}
// QmlJS
virtual bool visit(ThisExpression *) { return true; }
@@ -359,6 +387,23 @@ public:
virtual bool visit(DebuggerStatement *) { return true; }
virtual void endVisit(DebuggerStatement *) {}
virtual bool visit(Type *) { return true; }
virtual void endVisit(Type *) {}
virtual bool visit(TypeArgumentList *) { return true; }
virtual void endVisit(TypeArgumentList *) {}
virtual bool visit(TypeAnnotation *) { return true; }
virtual void endVisit(TypeAnnotation *) {}
virtual void throwRecursionDepthError() {}
quint16 recursionDepth() const { return m_recursionDepth; }
protected:
quint16 m_recursionDepth = 0;
friend class RecursionDepthCheck;
};
} } // namespace AST

File diff suppressed because it is too large Load Diff

View File

@@ -50,152 +50,150 @@ class QML_PARSER_EXPORT QmlJSGrammar
public:
enum VariousConstants {
EOF_SYMBOL = 0,
REDUCE_HERE = 125,
REDUCE_HERE = 128,
T_AND = 1,
T_AND_AND = 2,
T_AND_EQ = 3,
T_ARROW = 93,
T_AS = 110,
T_AUTOMATIC_SEMICOLON = 62,
T_ARROW = 95,
T_AS = 113,
T_AUTOMATIC_SEMICOLON = 64,
T_BREAK = 4,
T_CASE = 5,
T_CATCH = 6,
T_CLASS = 98,
T_CLASS = 100,
T_COLON = 7,
T_COMMA = 8,
T_COMMENT = 91,
T_COMPATIBILITY_SEMICOLON = 92,
T_CONST = 86,
T_COMMENT = 93,
T_COMPATIBILITY_SEMICOLON = 94,
T_CONST = 88,
T_CONTINUE = 9,
T_DEBUGGER = 88,
T_DEBUGGER = 90,
T_DEFAULT = 10,
T_DELETE = 11,
T_DIVIDE_ = 12,
T_DIVIDE_EQ = 13,
T_DO = 14,
T_DOT = 15,
T_ELLIPSIS = 95,
T_ELLIPSIS = 97,
T_ELSE = 16,
T_ENUM = 94,
T_ENUM = 96,
T_EQ = 17,
T_EQ_EQ = 18,
T_EQ_EQ_EQ = 19,
T_ERROR = 114,
T_EXPORT = 101,
T_EXTENDS = 99,
T_FALSE = 85,
T_FEED_JS_EXPRESSION = 118,
T_FEED_JS_MODULE = 120,
T_FEED_JS_SCRIPT = 119,
T_FEED_JS_STATEMENT = 117,
T_FEED_UI_OBJECT_MEMBER = 116,
T_FEED_UI_PROGRAM = 115,
T_ERROR = 117,
T_EXPORT = 103,
T_EXTENDS = 101,
T_FALSE = 87,
T_FEED_JS_EXPRESSION = 121,
T_FEED_JS_MODULE = 123,
T_FEED_JS_SCRIPT = 122,
T_FEED_JS_STATEMENT = 120,
T_FEED_UI_OBJECT_MEMBER = 119,
T_FEED_UI_PROGRAM = 118,
T_FINALLY = 20,
T_FOR = 21,
T_FORCE_BLOCK = 122,
T_FORCE_DECLARATION = 121,
T_FOR_LOOKAHEAD_OK = 123,
T_FROM = 102,
T_FUNCTION = 22,
T_GE = 23,
T_GET = 112,
T_GT = 24,
T_GT_GT = 25,
T_GT_GT_EQ = 26,
T_GT_GT_GT = 27,
T_GT_GT_GT_EQ = 28,
T_IDENTIFIER = 29,
T_IF = 30,
T_IMPORT = 108,
T_IN = 31,
T_INSTANCEOF = 32,
T_LBRACE = 33,
T_LBRACKET = 34,
T_LE = 35,
T_LET = 87,
T_LPAREN = 36,
T_LT = 37,
T_LT_LT = 38,
T_LT_LT_EQ = 39,
T_MINUS = 40,
T_MINUS_EQ = 41,
T_MINUS_MINUS = 42,
T_MULTILINE_STRING_LITERAL = 90,
T_NEW = 43,
T_NOT = 44,
T_NOT_EQ = 45,
T_NOT_EQ_EQ = 46,
T_NO_SUBSTITUTION_TEMPLATE = 103,
T_NULL = 83,
T_NUMERIC_LITERAL = 47,
T_OF = 111,
T_ON = 124,
T_OR = 48,
T_OR_EQ = 49,
T_OR_OR = 50,
T_PLUS = 51,
T_PLUS_EQ = 52,
T_PLUS_PLUS = 53,
T_PRAGMA = 109,
T_PROPERTY = 68,
T_PUBLIC = 107,
T_QUESTION = 54,
T_RBRACE = 55,
T_RBRACKET = 56,
T_READONLY = 70,
T_REMAINDER = 57,
T_REMAINDER_EQ = 58,
T_RESERVED_WORD = 89,
T_RETURN = 59,
T_RPAREN = 60,
T_SEMICOLON = 61,
T_SET = 113,
T_SIGNAL = 69,
T_STAR = 63,
T_STAR_EQ = 66,
T_STAR_STAR = 64,
T_STAR_STAR_EQ = 65,
T_STATIC = 100,
T_STRING_LITERAL = 67,
T_SUPER = 97,
T_SWITCH = 71,
T_TEMPLATE_HEAD = 104,
T_TEMPLATE_MIDDLE = 105,
T_TEMPLATE_TAIL = 106,
T_THIS = 72,
T_THROW = 73,
T_TILDE = 74,
T_TRUE = 84,
T_TRY = 75,
T_TYPEOF = 76,
T_VAR = 77,
T_VOID = 78,
T_WHILE = 79,
T_WITH = 80,
T_XOR = 81,
T_XOR_EQ = 82,
T_YIELD = 96,
T_FORCE_BLOCK = 125,
T_FORCE_DECLARATION = 124,
T_FOR_LOOKAHEAD_OK = 126,
T_FROM = 104,
T_FUNCTION = 23,
T_FUNCTION_STAR = 22,
T_GE = 24,
T_GET = 115,
T_GT = 25,
T_GT_GT = 26,
T_GT_GT_EQ = 27,
T_GT_GT_GT = 28,
T_GT_GT_GT_EQ = 29,
T_IDENTIFIER = 30,
T_IF = 31,
T_IMPORT = 111,
T_IN = 32,
T_INSTANCEOF = 33,
T_LBRACE = 34,
T_LBRACKET = 35,
T_LE = 36,
T_LET = 89,
T_LPAREN = 37,
T_LT = 38,
T_LT_LT = 39,
T_LT_LT_EQ = 40,
T_MINUS = 41,
T_MINUS_EQ = 42,
T_MINUS_MINUS = 43,
T_MULTILINE_STRING_LITERAL = 92,
T_NEW = 44,
T_NOT = 45,
T_NOT_EQ = 46,
T_NOT_EQ_EQ = 47,
T_NO_SUBSTITUTION_TEMPLATE = 106,
T_NULL = 85,
T_NUMERIC_LITERAL = 48,
T_OF = 114,
T_ON = 127,
T_OR = 49,
T_OR_EQ = 51,
T_OR_OR = 52,
T_PLUS = 53,
T_PLUS_EQ = 54,
T_PLUS_PLUS = 55,
T_PRAGMA = 112,
T_PROPERTY = 70,
T_PUBLIC = 110,
T_QUESTION = 56,
T_RBRACE = 57,
T_RBRACKET = 58,
T_READONLY = 72,
T_REMAINDER = 59,
T_REMAINDER_EQ = 60,
T_REQUIRED = 105,
T_RESERVED_WORD = 91,
T_RETURN = 61,
T_RPAREN = 62,
T_SEMICOLON = 63,
T_SET = 116,
T_SIGNAL = 71,
T_STAR = 65,
T_STAR_EQ = 68,
T_STAR_STAR = 66,
T_STAR_STAR_EQ = 67,
T_STATIC = 102,
T_STRING_LITERAL = 69,
T_SUPER = 99,
T_SWITCH = 73,
T_TEMPLATE_HEAD = 107,
T_TEMPLATE_MIDDLE = 108,
T_TEMPLATE_TAIL = 109,
T_THEN = 129,
T_THIS = 74,
T_THROW = 75,
T_TILDE = 76,
T_TRUE = 86,
T_TRY = 77,
T_TYPEOF = 78,
T_VAR = 79,
T_VERSION_NUMBER = 50,
T_VOID = 80,
T_WHILE = 81,
T_WITH = 82,
T_XOR = 83,
T_XOR_EQ = 84,
T_YIELD = 98,
ACCEPT_STATE = 1008,
RULE_COUNT = 586,
STATE_COUNT = 1009,
TERMINAL_COUNT = 126,
NON_TERMINAL_COUNT = 213,
ACCEPT_STATE = 1055,
RULE_COUNT = 591,
STATE_COUNT = 1056,
TERMINAL_COUNT = 130,
NON_TERMINAL_COUNT = 227,
GOTO_INDEX_OFFSET = 1009,
GOTO_INFO_OFFSET = 5937,
GOTO_CHECK_OFFSET = 5937
GOTO_INDEX_OFFSET = 1056,
GOTO_INFO_OFFSET = 6757,
GOTO_CHECK_OFFSET = 6757
};
static const char *const spell[];
static const short lhs[];
static const short rhs[];
#ifndef QLALR_NO_QMLJSGRAMMAR_DEBUG_INFO
static const int rule_index[];
static const int rule_info[];
#endif // QLALR_NO_QMLJSGRAMMAR_DEBUG_INFO
static const short goto_default[];
static const short action_default[];
static const short action_index[];

View File

@@ -728,6 +728,18 @@ static inline int classify8(const QChar *s, int parseModeFlags) {
}
}
}
} else if (s[2].unicode() == 'q') {
if (s[3].unicode() == 'u') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'r') {
if (s[6].unicode() == 'e') {
if (s[7].unicode() == 'd') {
return Lexer::T_REQUIRED;
}
}
}
}
}
}
}
}

View File

@@ -31,6 +31,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
#include <QtCore/QScopedValueRollback>
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
@@ -255,16 +256,29 @@ int Lexer::lex()
++_bracesCount;
Q_FALLTHROUGH();
case T_SEMICOLON:
_importState = ImportState::NoQmlImport;
Q_FALLTHROUGH();
case T_QUESTION:
case T_COLON:
case T_TILDE:
_delimited = true;
break;
case T_AUTOMATIC_SEMICOLON:
case T_AS:
_importState = ImportState::NoQmlImport;
Q_FALLTHROUGH();
default:
if (isBinop(_tokenKind))
_delimited = true;
break;
case T_IMPORT:
if (qmlMode() || (_handlingDirectives && previousTokenKind == T_DOT))
_importState = ImportState::SawImport;
if (isBinop(_tokenKind))
_delimited = true;
break;
case T_IF:
case T_FOR:
case T_WHILE:
@@ -462,6 +476,42 @@ int Lexer::scanToken()
again:
_validTokenText = false;
// handle comment can be called after a '/' has been read
// and returns true if it actually encountered a comment
auto handleComment = [this](){
if (_char == QLatin1Char('*')) {
scanChar();
while (_codePtr <= _endPtr) {
if (_char == QLatin1Char('*')) {
scanChar();
if (_char == QLatin1Char('/')) {
scanChar();
if (_engine) {
_engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
tokenStartLine(), tokenStartColumn() + 2);
}
return true;
}
} else {
scanChar();
}
}
} else if (_char == QLatin1Char('/')) {
while (_codePtr <= _endPtr && !isLineTerminator()) {
scanChar();
}
if (_engine) {
_engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
tokenStartLine(), tokenStartColumn() + 2);
}
return true;
}
return false;
};
while (_char.isSpace()) {
if (isLineTerminator()) {
if (_restrictedKeyword) {
@@ -569,41 +619,17 @@ again:
case ':': return T_COLON;
case '/':
if (_char == QLatin1Char('*')) {
scanChar();
while (_codePtr <= _endPtr) {
if (_char == QLatin1Char('*')) {
scanChar();
if (_char == QLatin1Char('/')) {
scanChar();
if (_engine) {
_engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4,
tokenStartLine(), tokenStartColumn() + 2);
}
goto again;
}
} else {
scanChar();
}
}
} else if (_char == QLatin1Char('/')) {
while (_codePtr <= _endPtr && !isLineTerminator()) {
scanChar();
}
if (_engine) {
_engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2,
tokenStartLine(), tokenStartColumn() + 2);
}
if (handleComment())
goto again;
} if (_char == QLatin1Char('=')) {
else if (_char == QLatin1Char('=')) {
scanChar();
return T_DIVIDE_EQ;
}
return T_DIVIDE_;
case '.':
if (_importState == ImportState::SawImport)
return T_DOT;
if (isDecimalDigit(_char.unicode()))
return scanNumber(ch);
if (_char == QLatin1Char('.')) {
@@ -714,7 +740,10 @@ again:
case '7':
case '8':
case '9':
return scanNumber(ch);
if (_importState == ImportState::SawImport)
return scanVersionNumber(ch);
else
return scanNumber(ch);
default: {
uint c = ch.unicode();
@@ -794,6 +823,21 @@ again:
if (!identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
if (kind == T_FUNCTION) {
continue_skipping:
while (_codePtr < _endPtr && _char.isSpace())
scanChar();
if (_char == QLatin1Char('*')) {
_tokenLength = _codePtr - _tokenStartPtr - 1;
kind = T_FUNCTION_STAR;
scanChar();
} else if (_char == QLatin1Char('/')) {
scanChar();
if (handleComment())
goto continue_skipping;
}
}
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)
_tokenSpell = _engine->newStringRef(_tokenText);
@@ -1132,6 +1176,26 @@ int Lexer::scanNumber(QChar ch)
return T_NUMERIC_LITERAL;
}
int Lexer::scanVersionNumber(QChar ch)
{
if (ch == QLatin1Char('0')) {
_tokenValue = 0;
return T_VERSION_NUMBER;
}
int acc = 0;
acc += ch.digitValue();
while (_char.isDigit()) {
acc *= 10;
acc += _char.digitValue();
scanChar(); // consume the digit
}
_tokenValue = acc;
return T_VERSION_NUMBER;
}
bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
{
_tokenText.resize(0);
@@ -1352,6 +1416,7 @@ static const int uriTokens[] = {
QmlJSGrammar::T_FINALLY,
QmlJSGrammar::T_FOR,
QmlJSGrammar::T_FUNCTION,
QmlJSGrammar::T_FUNCTION_STAR,
QmlJSGrammar::T_IF,
QmlJSGrammar::T_IN,
QmlJSGrammar::T_OF,
@@ -1388,6 +1453,13 @@ static inline bool isUriToken(int token)
bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
{
auto setError = [error, this](QString message) {
error->message = std::move(message);
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
};
QScopedValueRollback<bool> directivesGuard(_handlingDirectives, true);
Q_ASSERT(!_qmlMode);
lex(); // fetch the first token
@@ -1408,9 +1480,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
if (! (directiveName == QLatin1String("pragma") ||
directiveName == QLatin1String("import"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser", "Syntax error"));
return false; // not a valid directive name
}
@@ -1418,9 +1488,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
if (directiveName == QLatin1String("pragma")) {
// .pragma library
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser", "Syntax error"));
return false; // expected `library
}
@@ -1442,20 +1510,15 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
pathOrUri = tokenText();
if (!pathOrUri.endsWith(QLatin1String("js"))) {
error->message = QCoreApplication::translate("QmlParser","Imported file must be a script");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser","Imported file must be a script"));
return false;
}
} else if (_tokenKind == T_IDENTIFIER) {
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_VERSION_NUMBER . T_VERSION_NUMBER as T_IDENTIFIER
while (true) {
if (!isUriToken(_tokenKind)) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser","Invalid module URI"));
return false;
}
@@ -1463,9 +1526,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser","Invalid module URI"));
return false;
}
if (_tokenKind != QmlJSGrammar::T_DOT)
@@ -1475,21 +1536,30 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser","Invalid module URI"));
return false;
}
}
if (_tokenKind != T_NUMERIC_LITERAL) {
error->message = QCoreApplication::translate("QmlParser","Module import requires a version");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
if (_tokenKind != T_VERSION_NUMBER) {
setError(QCoreApplication::translate("QmlParser","Module import requires a version"));
return false; // expected the module version number
}
version = tokenText();
lex();
if (_tokenKind != T_DOT) {
setError(QCoreApplication::translate( "QmlParser", "Module import requires a minor version (missing dot)"));
return false; // expected the module version number
}
version += QLatin1Char('.');
lex();
if (_tokenKind != T_VERSION_NUMBER) {
setError(QCoreApplication::translate( "QmlParser", "Module import requires a minor version (missing number)"));
return false; // expected the module version number
}
version += tokenText();
}
//
@@ -1497,34 +1567,27 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
//
if (! (lex() == T_AS && tokenStartLine() == lineNumber)) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
setError(QCoreApplication::translate("QmlParser", "File import requires a qualifier"));
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
setError(QCoreApplication::translate("QmlParser", "Module import requires a qualifier"));
if (tokenStartLine() != lineNumber) {
error->loc.startLine = lineNumber;
error->loc.startColumn = column;
} else {
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
}
return false; // expected `as'
}
if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
setError(QCoreApplication::translate("QmlParser", "File import requires a qualifier"));
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser", "Module import requires a qualifier"));
return false; // expected module name
}
const QString module = tokenText();
if (!module.at(0).isUpper()) {
error->message = QCoreApplication::translate("QmlParser","Invalid import qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser","Invalid import qualifier"));
return false;
}
@@ -1535,9 +1598,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
}
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
setError(QCoreApplication::translate("QmlParser", "Syntax error"));
return false; // the directives cannot span over multiple lines
}

View File

@@ -109,6 +109,11 @@ public:
StaticIsKeyword = 0x4
};
enum class ImportState {
SawImport,
NoQmlImport
};
public:
Lexer(Engine *engine);
@@ -173,6 +178,7 @@ private:
inline void scanChar();
int scanToken();
int scanNumber(QChar ch);
int scanVersionNumber(QChar ch);
enum ScanStringMode {
SingleQuote = '\'',
DoubleQuote = '"',
@@ -227,6 +233,7 @@ private:
int _tokenLength;
int _tokenLine;
int _tokenColumn;
ImportState _importState = ImportState::NoQmlImport;
bool _validTokenText;
bool _prohibitAutomaticSemicolon;
@@ -238,6 +245,7 @@ private:
bool _skipLinefeed = false;
int _generatorLevel = 0;
bool _staticIsKeyword = false;
bool _handlingDirectives = false;
};
} // end of namespace QmlJS

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#line 178 "qmljs.g"
#line 182 "qmljs.g"
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
@@ -122,6 +122,9 @@ public:
AST::ExportsList *ExportsList;
AST::ExportClause *ExportClause;
AST::ExportDeclaration *ExportDeclaration;
AST::TypeAnnotation *TypeAnnotation;
AST::TypeArgumentList *TypeArgumentList;
AST::Type *Type;
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
@@ -139,6 +142,7 @@ public:
AST::UiArrayMemberList *UiArrayMemberList;
AST::UiQualifiedId *UiQualifiedId;
AST::UiEnumMemberList *UiEnumMemberList;
AST::UiVersionSpecifier *UiVersionSpecifier;
};
public:
@@ -217,6 +221,9 @@ protected:
inline QStringRef &stringRef(int index)
{ return string_stack [tos + index - 1]; }
inline QStringRef &rawStringRef(int index)
{ return rawString_stack [tos + index - 1]; }
inline AST::SourceLocation &loc(int index)
{ return location_stack [tos + index - 1]; }
@@ -225,13 +232,25 @@ protected:
void pushToken(int token);
int lookaheadToken(Lexer *lexer);
static DiagnosticMessage compileError(const AST::SourceLocation &location,
const QString &message, Severity::Enum kind = Severity::Error)
{
DiagnosticMessage error;
error.loc = location;
error.message = message;
error.kind = kind;
return error;
}
void syntaxError(const AST::SourceLocation &location, const char *message) {
diagnostic_messages.append(DiagnosticMessage(Severity::Error, location, QLatin1String(message)));
diagnostic_messages.append(compileError(location, QLatin1String(message)));
}
void syntaxError(const AST::SourceLocation &location, const QString &message) {
diagnostic_messages.append(DiagnosticMessage(Severity::Error, location, message));
diagnostic_messages.append(compileError(location, message));
}
bool ensureNoFunctionTypeAnnotations(AST::TypeAnnotation *returnTypeAnnotation, AST::FormalParameterList *formals);
protected:
Engine *driver;
MemoryPool *pool;
@@ -241,6 +260,7 @@ protected:
int *state_stack = nullptr;
AST::SourceLocation *location_stack = nullptr;
QVector<QStringRef> string_stack;
QVector<QStringRef> rawString_stack;
AST::Node *program = nullptr;
@@ -252,11 +272,13 @@ protected:
double dval;
AST::SourceLocation loc;
QStringRef spell;
QStringRef raw;
};
int yytoken = -1;
double yylval = 0.;
QStringRef yytokenspell;
QStringRef yytokenraw;
AST::SourceLocation yylloc;
AST::SourceLocation yyprevlloc;
@@ -281,27 +303,27 @@ protected:
#line 1511 "qmljs.g"
#line 1686 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE1 128
#define J_SCRIPT_REGEXPLITERAL_RULE1 144
#line 1523 "qmljs.g"
#line 1698 "qmljs.g"
#define J_SCRIPT_REGEXPLITERAL_RULE2 129
#define J_SCRIPT_REGEXPLITERAL_RULE2 145
#line 3022 "qmljs.g"
#line 3198 "qmljs.g"
#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE 421
#define J_SCRIPT_EXPRESSIONSTATEMENTLOOKAHEAD_RULE 435
#line 3653 "qmljs.g"
#line 3850 "qmljs.g"
#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE 499
#define J_SCRIPT_CONCISEBODYLOOKAHEAD_RULE 505
#line 4181 "qmljs.g"
#line 4389 "qmljs.g"
#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE 569
#define J_SCRIPT_EXPORTDECLARATIONLOOKAHEAD_RULE 574
#line 4469 "qmljs.g"
#line 4673 "qmljs.g"
QT_QML_END_NAMESPACE

View File

@@ -66,7 +66,7 @@ public:
return _message;
}
void setMessage(Type type)
void setMessage(StaticAnalysis::Type type)
{
_message = Message(type, _location);
}
@@ -511,7 +511,7 @@ protected:
}
private:
void addMessage(Type type, const SourceLocation &loc, const QString &arg1 = QString())
void addMessage(StaticAnalysis::Type type, const SourceLocation &loc, const QString &arg1 = QString())
{
_messages.append(Message(type, loc, arg1));
}
@@ -695,12 +695,12 @@ QList<Message> Check::operator()()
return _messages;
}
void Check::enableMessage(Type type)
void Check::enableMessage(StaticAnalysis::Type type)
{
_enabledMessages.insert(type);
}
void Check::disableMessage(Type type)
void Check::disableMessage(StaticAnalysis::Type type)
{
_enabledMessages.remove(type);
}
@@ -1267,7 +1267,7 @@ bool Check::visit(BinaryExpression *ast)
const QLatin1Char newline('\n');
if (ast->op == QSOperator::Add || ast->op == QSOperator::Sub) {
QChar match;
Type msg;
StaticAnalysis::Type msg;
if (ast->op == QSOperator::Add) {
match = '+';
msg = WarnConfusingPluses;
@@ -1522,7 +1522,7 @@ void Check::addMessage(const Message &message)
}
}
void Check::addMessage(Type type, const SourceLocation &location, const QString &arg1, const QString &arg2)
void Check::addMessage(StaticAnalysis::Type type, const SourceLocation &location, const QString &arg1, const QString &arg2)
{
addMessage(Message(type, location, arg1, arg2));
}