From e850586b770ab9330347354b01c31eff1053ad78 Mon Sep 17 00:00:00 2001 From: Christian Kamm <christian.d.kamm@nokia.com> Date: Tue, 6 Sep 2011 12:59:30 +0200 Subject: [PATCH] QmlJS checks: Warn about inappropriate use of constructor functions. Change-Id: Iaedaaa88915f2010bfdd0d2b5ca95f01f8663ed7 Reviewed-on: http://codereview.qt.nokia.com/4254 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com> --- src/libs/qmljs/qmljscheck.cpp | 61 +++++++++++++++++++++++++++++++++-- src/libs/qmljs/qmljscheck.h | 8 ++++- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 71257250e2a..90aa25b11aa 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -408,9 +408,10 @@ Check::Check(Document::Ptr doc, const ContextPtr &context) , _scopeChain(doc, _context) , _scopeBuilder(&_scopeChain) , _options(WarnDangerousNonStrictEqualityChecks | WarnBlocks | WarnWith - | WarnVoid | WarnCommaExpression | WarnExpressionStatement - | WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration - | WarnCaseWithoutFlowControlEnd | ErrCheckTypeErrors) + | WarnVoid | WarnCommaExpression | WarnExpressionStatement + | WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration + | WarnCaseWithoutFlowControlEnd | WarnNonCapitalizedNew + | WarnCallsOfCapitalizedFunctions | ErrCheckTypeErrors) , _lastValue(0) { } @@ -891,6 +892,60 @@ bool Check::visit(DefaultClause *ast) return true; } +static QString functionName(ExpressionNode *ast, SourceLocation *location) +{ + if (IdentifierExpression *id = cast<IdentifierExpression *>(ast)) { + if (id->name) { + *location = id->identifierToken; + return id->name->asString(); + } + } else if (FieldMemberExpression *fme = cast<FieldMemberExpression *>(ast)) { + if (fme->name) { + *location = fme->identifierToken; + return fme->name->asString(); + } + } + return QString(); +} + +void Check::checkNewExpression(ExpressionNode *ast) +{ + if (!(_options & WarnNonCapitalizedNew)) + return; + SourceLocation location; + const QString name = functionName(ast, &location); + if (name.isEmpty()) + return; + if (!name.at(0).isUpper()) { + warning(location, tr("'new' should only be used with functions that start with an uppercase letter")); + } +} + +bool Check::visit(NewExpression *ast) +{ + checkNewExpression(ast->expression); + return true; +} + +bool Check::visit(NewMemberExpression *ast) +{ + checkNewExpression(ast->base); + return true; +} + +bool Check::visit(CallExpression *ast) +{ + // check for capitalized function name being called + if (_options & WarnCallsOfCapitalizedFunctions) { + SourceLocation location; + const QString name = functionName(ast->base, &location); + if (!name.isEmpty() && name.at(0).isUpper()) { + warning(location, tr("calls of functions that start with an uppercase letter should use 'new'")); + } + } + return true; +} + /// When something is changed here, also change ReadingContext::lookupProperty in /// texttomodelmerger.cpp /// ### Maybe put this into the context as a helper method. diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index af4b75c2c3c..310d91880f8 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -72,7 +72,9 @@ public: WarnDuplicateDeclaration = 1 << 9, WarnDeclarationsNotStartOfFunction = 1 << 10, WarnCaseWithoutFlowControlEnd = 1 << 11, - ErrCheckTypeErrors = 1 << 12 + WarnNonCapitalizedNew = 1 << 12, + WarnCallsOfCapitalizedFunctions = 1 << 13, + ErrCheckTypeErrors = 1 << 14 }; Q_DECLARE_FLAGS(Options, Option) @@ -111,6 +113,9 @@ protected: virtual bool visit(AST::DoWhileStatement *ast); virtual bool visit(AST::CaseClause *ast); virtual bool visit(AST::DefaultClause *ast); + virtual bool visit(AST::NewExpression *ast); + virtual bool visit(AST::NewMemberExpression *ast); + virtual bool visit(AST::CallExpression *ast); virtual void endVisit(QmlJS::AST::UiObjectInitializer *); @@ -121,6 +126,7 @@ private: void checkAssignInCondition(AST::ExpressionNode *condition); void checkEndsWithControlFlow(AST::StatementList *statements, AST::SourceLocation errorLoc); void checkProperty(QmlJS::AST::UiQualifiedId *); + void checkNewExpression(AST::ExpressionNode *node); void warning(const AST::SourceLocation &loc, const QString &message); void error(const AST::SourceLocation &loc, const QString &message); -- GitLab