forked from qt-creator/qt-creator
		
	QmlJSCheck: adding more checks
We are checking for duplicate ids and duplicate property definitions now.
This commit is contained in:
		| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user