aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-11-28 14:58:01 +0100
committerChristian Kamm <christian.d.kamm@nokia.com>2011-11-29 08:25:51 +0100
commita920096c97e8a4abc3859a4252fe33317305c3f7 (patch)
tree0cb43d7987af560e8a08a060a112e92449c1fb01 /src
parentc00cbcf5740c37f0a8f8d294c5c8bbf485a96e1a (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.cpp49
-rw-r--r--src/libs/qmljs/qmljscheck.h5
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);