diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-11-28 14:58:01 +0100 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-11-29 08:25:51 +0100 |
commit | a920096c97e8a4abc3859a4252fe33317305c3f7 (patch) | |
tree | 0cb43d7987af560e8a08a060a112e92449c1fb01 /src | |
parent | c00cbcf5740c37f0a8f8d294c5c8bbf485a96e1a (diff) |
QmlJS checks: Accept 'fallthrough' comment to terminate case blocks.
Change-Id: Icf71416e8aa892089b0918529b94f4cd6a1db5a3
Reviewed-by: Leandro Melo <leandro.melo@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/qmljs/qmljscheck.cpp | 49 | ||||
-rw-r--r-- | src/libs/qmljs/qmljscheck.h | 5 |
2 files changed, 42 insertions, 12 deletions
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 0b5eb1943c..3b1bde0438 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -1086,15 +1086,24 @@ bool Check::visit(DoWhileStatement *ast) return true; } -bool Check::visit(CaseClause *ast) +bool Check::visit(CaseBlock *ast) { - checkEndsWithControlFlow(ast->statements, ast->caseToken); - return true; -} - -bool Check::visit(DefaultClause *ast) -{ - checkEndsWithControlFlow(ast->statements, ast->defaultToken); + QList< QPair<SourceLocation, StatementList *> > clauses; + for (CaseClauses *it = ast->clauses; it; it = it->next) + clauses += qMakePair(it->clause->caseToken, it->clause->statements); + if (ast->defaultClause) + clauses += qMakePair(ast->defaultClause->defaultToken, ast->defaultClause->statements); + for (CaseClauses *it = ast->moreClauses; it; it = it->next) + clauses += qMakePair(it->clause->caseToken, it->clause->statements); + + for (int i = 0; i < clauses.size(); ++i) { + SourceLocation nextToken; + if (i + 1 < clauses.size()) + nextToken = clauses[i + 1].first; + else + nextToken = ast->rbraceToken; + checkCaseFallthrough(clauses[i].second, clauses[i].first, nextToken); + } return true; } @@ -1435,13 +1444,35 @@ void Check::checkAssignInCondition(AST::ExpressionNode *condition) } } -void Check::checkEndsWithControlFlow(StatementList *statements, SourceLocation errorLoc) +void Check::checkCaseFallthrough(StatementList *statements, SourceLocation errorLoc, SourceLocation nextLoc) { if (!statements) return; ReachesEndCheck check; if (check(statements)) { + // check for fallthrough comments + if (nextLoc.isValid()) { + quint32 afterLastStatement = 0; + for (StatementList *it = statements; it; it = it->next) { + if (!it->next) + afterLastStatement = it->statement->lastSourceLocation().end(); + } + + foreach (const SourceLocation &comment, _doc->engine()->comments()) { + if (comment.begin() < afterLastStatement + || comment.end() > nextLoc.begin()) + continue; + + const QString &commentText = _doc->source().mid(comment.begin(), comment.length); + if (commentText.contains(QLatin1String("fall through")) + || commentText.contains(QLatin1String("fall-through")) + || commentText.contains(QLatin1String("fallthrough"))) { + return; + } + } + } + addMessage(WarnCaseWithoutFlowControl, errorLoc); } } diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index 6c8f88396d..39ed5493c5 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -90,8 +90,7 @@ protected: virtual bool visit(AST::LocalForStatement *ast); virtual bool visit(AST::WhileStatement *ast); virtual bool visit(AST::DoWhileStatement *ast); - virtual bool visit(AST::CaseClause *ast); - virtual bool visit(AST::DefaultClause *ast); + virtual bool visit(AST::CaseBlock *ast); virtual bool visit(AST::NewExpression *ast); virtual bool visit(AST::NewMemberExpression *ast); virtual bool visit(AST::CallExpression *ast); @@ -108,7 +107,7 @@ private: AST::UiObjectInitializer *initializer); const Value *checkScopeObjectMember(const AST::UiQualifiedId *id); void checkAssignInCondition(AST::ExpressionNode *condition); - void checkEndsWithControlFlow(AST::StatementList *statements, AST::SourceLocation errorLoc); + void checkCaseFallthrough(AST::StatementList *statements, AST::SourceLocation errorLoc, AST::SourceLocation nextLoc); void checkProperty(QmlJS::AST::UiQualifiedId *); void checkNewExpression(AST::ExpressionNode *node); void checkBindingRhs(AST::Statement *statement); |