Commit 0eb18f85 authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlJSCheck: adding more checks

We are checking for duplicate ids and duplicate property definitions now.
parent 00561850
......@@ -72,6 +72,20 @@ SourceLocation QmlJS::locationFromRange(const SourceLocation &start,
start.startColumn);
}
SourceLocation QmlJS::fullLocationForQualifiedId(AST::UiQualifiedId *qualifiedId)
{
SourceLocation start = qualifiedId->identifierToken;
SourceLocation end = qualifiedId->identifierToken;
for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
if (iter->name)
end = iter->identifierToken;
}
return locationFromRange(start, end);
}
DiagnosticMessage QmlJS::errorMessage(const AST::SourceLocation &loc, const QString &message)
{
return DiagnosticMessage(DiagnosticMessage::Error, loc, message);
......@@ -387,6 +401,29 @@ bool Check::visit(UiProgram *)
return true;
}
bool Check::visit(UiObjectInitializer *)
{
m_propertyStack.push(StringSet());
return true;
}
void Check::endVisit(UiObjectInitializer *)
{
m_propertyStack.pop();
}
void Check::checkProperty(UiQualifiedId *qualifiedId)
{
const QString id = Bind::toString(qualifiedId);
if (id.at(0).isLower()) {
if (m_propertyStack.top().contains(id)) {
error(fullLocationForQualifiedId(qualifiedId),
Check::tr("properties can only be assigned once"));
}
m_propertyStack.top().insert(id);
}
}
bool Check::visit(UiObjectDefinition *ast)
{
visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
......@@ -396,6 +433,7 @@ bool Check::visit(UiObjectDefinition *ast)
bool Check::visit(UiObjectBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);
checkProperty(ast->qualifiedId);
visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
return false;
......@@ -457,12 +495,20 @@ bool Check::visit(UiScriptBinding *ast)
return false;
}
if (id.isEmpty() || ! id[0].isLower()) {
error(loc, Check::tr("ids must be lower case"));
if (id.isEmpty() || (!id[0].isLower() && id[0] != '_')) {
error(loc, Check::tr("ids must be lower case or start with underscore"));
return false;
}
if (m_ids.contains(id)) {
error(loc, Check::tr("ids must be unique"));
return false;
}
m_ids.insert(id);
}
checkProperty(ast->qualifiedId);
const Value *lhsValue = checkScopeObjectMember(ast->qualifiedId);
if (lhsValue) {
// ### Fix the evaluator to accept statements!
......@@ -493,6 +539,7 @@ bool Check::visit(UiScriptBinding *ast)
bool Check::visit(UiArrayBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);
checkProperty(ast->qualifiedId);
return true;
}
......
......@@ -36,6 +36,8 @@
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QSet>
#include <QtCore/QStack>
#include <QtGui/QColor>
namespace QmlJS {
......@@ -44,12 +46,18 @@ class QMLJS_EXPORT Check: protected AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QmlJS::Check)
typedef QSet<QString> StringSet;
public:
Check(Document::Ptr doc, const Snapshot &snapshot, const Interpreter::Context *linkedContextNoScope);
virtual ~Check();
QList<DiagnosticMessage> operator()();
void setIgnoreTypeErrors(bool ignore)
{ _ignoreTypeErrors = ignore; }
enum Option {
WarnDangerousNonStrictEqualityChecks = 1 << 0,
WarnAllNonStrictEqualityChecks = 1 << 1,
......@@ -79,6 +87,7 @@ protected:
virtual bool visit(AST::FieldMemberExpression *ast);
virtual bool visit(AST::FunctionDeclaration *ast);
virtual bool visit(AST::FunctionExpression *ast);
virtual bool visit(AST::UiObjectInitializer *);
virtual bool visit(AST::BinaryExpression *ast);
virtual bool visit(AST::Block *ast);
......@@ -94,12 +103,15 @@ protected:
virtual bool visit(AST::CaseClause *ast);
virtual bool visit(AST::DefaultClause *ast);
virtual void endVisit(QmlJS::AST::UiObjectInitializer *);
private:
void visitQmlObject(AST::Node *ast, AST::UiQualifiedId *typeId,
AST::UiObjectInitializer *initializer);
const Interpreter::Value *checkScopeObjectMember(const AST::UiQualifiedId *id);
void checkAssignInCondition(AST::ExpressionNode *condition);
void checkEndsWithControlFlow(AST::StatementList *statements, AST::SourceLocation errorLoc);
void checkProperty(QmlJS::AST::UiQualifiedId *);
void warning(const AST::SourceLocation &loc, const QString &message);
void error(const AST::SourceLocation &loc, const QString &message);
......@@ -119,12 +131,17 @@ private:
const Interpreter::Value *_lastValue;
QList<AST::Node *> _chain;
QSet<QString> m_ids;
QStack<StringSet> m_propertyStack;
};
QMLJS_EXPORT QColor toQColor(const QString &qmlColorString);
QMLJS_EXPORT AST::SourceLocation locationFromRange(const AST::SourceLocation &start,
const AST::SourceLocation &end);
QMLJS_EXPORT AST::SourceLocation fullLocationForQualifiedId(AST::UiQualifiedId *);
QMLJS_EXPORT DiagnosticMessage errorMessage(const AST::SourceLocation &loc,
const QString &message);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment