mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 329497 - checker for no break at the end of case
This commit is contained in:
parent
acfb30df58
commit
83ea511e24
9 changed files with 800 additions and 5 deletions
|
@ -56,4 +56,7 @@ problem.description.ReturnStyle = Checks for return statements that do no return
|
|||
checker.name.SuspiciousSemicolon = Suspicious semicolon
|
||||
problem.name.SuspiciousSemicolon = Suspicious semicolon
|
||||
problem.messagePattern.SuspiciousSemicolon = Suspicious semicolon
|
||||
problem.description.SuspiciousSemicolon = A semicolon is used as a null statement in a condition. For example, 'if(expression);'
|
||||
problem.description.SuspiciousSemicolon = A semicolon is used as a null statement in a condition. For example, 'if(expression);'
|
||||
checker.name.CaseBreak = No break at end of case
|
||||
problem.description.CaseBreak = Looks for "case" statements which end without a "break" statement statement statement
|
||||
problem.messagePattern.CaseBreak = No break at the end of this case
|
|
@ -306,5 +306,19 @@
|
|||
name="%problem.name.SuspiciousSemicolon">
|
||||
</problem>
|
||||
</checker>
|
||||
<checker
|
||||
class="org.eclipse.cdt.codan.internal.checkers.CaseBreakChecker"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.CaseBreak"
|
||||
name="%checker.name.CaseBreak">
|
||||
<problem
|
||||
category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
|
||||
defaultEnabled="true"
|
||||
defaultSeverity="Warning"
|
||||
description="%problem.description.CaseBreak"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem"
|
||||
messagePattern="%problem.messagePattern.CaseBreak"
|
||||
name="%checker.name.CaseBreak">
|
||||
</problem>
|
||||
</checker>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Gil Barash
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Gil Barash - Initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.internal.checkers;
|
||||
|
||||
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
|
||||
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
|
||||
import org.eclipse.cdt.codan.core.model.ICheckerWithPreferences;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTContinueStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
|
||||
public class CaseBreakChecker extends AbstractIndexAstChecker implements
|
||||
ICheckerWithPreferences {
|
||||
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem"; //$NON-NLS-1$
|
||||
public static final String PARAM_LAST_CASE = "last_case_param"; //$NON-NLS-1$
|
||||
public static final String PARAM_EMPTY_CASE = "empty_case_param"; //$NON-NLS-1$
|
||||
public static final String PARAM_NO_BREAK_COMMENT = "no_break_comment"; //$NON-NLS-1$
|
||||
public static final String DEFAULT_NO_BREAK_COMMENT = "no break"; //$NON-NLS-1$
|
||||
private CommentsIterator _commentsIt; // Iterator over comments
|
||||
private Boolean _checkLastCase; // Should we check the last case in the switch?
|
||||
private Boolean _checkEmptyCase; // Should we check an empty case (a case without any statements within it)
|
||||
private String _noBreakComment; // The comment suppressing this warning
|
||||
|
||||
/**
|
||||
* This class receives the comments of the AST and iterates over them
|
||||
*/
|
||||
class CommentsIterator {
|
||||
private int _next; // The next comment's index
|
||||
private IASTComment[] _comments;
|
||||
|
||||
CommentsIterator(IASTComment[] comments) {
|
||||
_comments = comments;
|
||||
_next = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Is there an unvisited comment?
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return (_next < _comments.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The next comment (doesn't automatically advance to the next
|
||||
* comment.
|
||||
* i.e. Calling this function twice may return the same value).
|
||||
* See {@link#advance}
|
||||
*/
|
||||
public IASTComment getNext() {
|
||||
return (_comments[_next]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node The node to compare the comment's location to
|
||||
* @return Is the next comment located after 'node'
|
||||
*/
|
||||
public boolean isNextAfterThis(IASTNode node) {
|
||||
return (_comments[_next].getFileLocation().getNodeOffset() > node
|
||||
.getFileLocation().getNodeOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node The node to compare the comment's location to
|
||||
* @return Is the next comment located after 'node' ends
|
||||
*/
|
||||
public boolean isNextAfterThisEnds(IASTNode node) {
|
||||
return (_comments[_next].getFileLocation().getNodeOffset() > node
|
||||
.getFileLocation().getNodeOffset()
|
||||
+ node.getFileLocation().getNodeLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance to the next comment
|
||||
*/
|
||||
public void advance() {
|
||||
_next++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This visitor looks for "switch" statements and invokes "SwitchVisitor" on
|
||||
* them
|
||||
*/
|
||||
class SwitchFindingVisitor extends ASTVisitor {
|
||||
protected IASTStatement _switchStatement; // The "switch" we're visiting (used by inheriting classes to avoid re-visiting the same "switch" again)
|
||||
|
||||
SwitchFindingVisitor() {
|
||||
shouldVisitStatements = true;
|
||||
_switchStatement = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTStatement statement) {
|
||||
if (statement instanceof IASTSwitchStatement) {
|
||||
// Are we already visiting this statement?
|
||||
if (_switchStatement == null
|
||||
|| !statement.equals(_switchStatement)) {
|
||||
SwitchVisitor switch_visitor = new SwitchVisitor(statement);
|
||||
statement.accept(switch_visitor);
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This visitor visits a switch statement and checks the end of each
|
||||
* "case" statement (to see that it ends with a "break").
|
||||
* Because it extends SwitchFindingVisitor is would also check nested
|
||||
* "switch"s
|
||||
*/
|
||||
class SwitchVisitor extends SwitchFindingVisitor {
|
||||
private IASTStatement _last_case_stmnt;
|
||||
private boolean _first_case_statement;
|
||||
private int _last_break_stmnt_offset;
|
||||
private int _last_normal_stmnt_offset;
|
||||
private int _last_case_stmnt_offset;
|
||||
|
||||
SwitchVisitor(IASTStatement switch_statement) {
|
||||
shouldVisitStatements = true;
|
||||
_first_case_statement = true;
|
||||
_switchStatement = switch_statement;
|
||||
_last_break_stmnt_offset = 0;
|
||||
_last_normal_stmnt_offset = 0;
|
||||
_last_case_stmnt_offset = 0;
|
||||
_last_case_stmnt = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Is this an "empty" case (i.e. with no statements in it)
|
||||
*/
|
||||
private boolean isEmptyCase() {
|
||||
return _last_case_stmnt_offset > _last_normal_stmnt_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Was a "break" statement the last statement in this case
|
||||
*/
|
||||
private boolean breakFoundLast() {
|
||||
return _last_normal_stmnt_offset < _last_break_stmnt_offset
|
||||
&& _last_case_stmnt_offset < _last_break_stmnt_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the last case we've visited
|
||||
*
|
||||
* @param comment The comment ending this case (may be NULL)
|
||||
*/
|
||||
private void checkLastCase(IASTComment comment) {
|
||||
if (comment != null) {
|
||||
String str = new String(comment.getComment());
|
||||
if (comment.isBlockComment())
|
||||
str = str.substring(2, str.length() - 2);
|
||||
else
|
||||
str = str.substring(2);
|
||||
str = str.trim();
|
||||
if (str.equalsIgnoreCase(_noBreakComment))
|
||||
return;
|
||||
}
|
||||
if (_last_case_stmnt == null)
|
||||
return; // This is an empty switch
|
||||
if (breakFoundLast())
|
||||
return; // There was a "break" before the current statement
|
||||
if (!isEmptyCase() || _checkEmptyCase) {
|
||||
reportProblem(ER_ID, _last_case_stmnt, (Object) null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTStatement statement) {
|
||||
if (statement instanceof IASTCaseStatement
|
||||
|| statement instanceof IASTDefaultStatement) {
|
||||
if (_first_case_statement) {
|
||||
/*
|
||||
* This is the first "case", i.e. the beginning of the
|
||||
* "switch"
|
||||
*/
|
||||
_first_case_statement = false;
|
||||
} else {
|
||||
/*
|
||||
* This is not the 1st "case", meaning that a previous case
|
||||
* has just ended,
|
||||
* Let's check that case and see how it ended...
|
||||
*/
|
||||
IASTComment comment = null;
|
||||
// Do we have a comment which is before this "case" statement (but after the previous statement)?
|
||||
while (_commentsIt.hasNext()
|
||||
&& !_commentsIt.isNextAfterThis(statement)) {
|
||||
comment = _commentsIt.getNext();
|
||||
_commentsIt.advance();
|
||||
}
|
||||
/*
|
||||
* 'comment' is the last comment found in this case (after
|
||||
* the last statement in this "case"
|
||||
*/
|
||||
checkLastCase(comment);
|
||||
}
|
||||
/* Update variables with the new opened "case" */
|
||||
_last_case_stmnt_offset = statement.getFileLocation()
|
||||
.getNodeOffset();
|
||||
_last_case_stmnt = statement;
|
||||
} else if (isBreakOrExitStatement(statement)) { // A "break" statement
|
||||
_last_break_stmnt_offset = statement.getFileLocation()
|
||||
.getNodeOffset();
|
||||
} else { // a non-switch related statement
|
||||
_last_normal_stmnt_offset = statement.getFileLocation()
|
||||
.getNodeOffset();
|
||||
}
|
||||
/* advance comments we already passed */
|
||||
while (_commentsIt.hasNext()
|
||||
&& !_commentsIt.isNextAfterThis(statement))
|
||||
_commentsIt.advance();
|
||||
return super.visit(statement); // This would handle nested "switch"s
|
||||
}
|
||||
|
||||
@Override
|
||||
public int leave(IASTStatement statement) {
|
||||
/*
|
||||
* Are we leaving the "switch" altogether? (we need to see how the
|
||||
* last "case" ended)
|
||||
*/
|
||||
if (_checkLastCase && statement instanceof IASTCompoundStatement
|
||||
&& statement.getParent() == _switchStatement) {
|
||||
IASTComment comment = null;
|
||||
// is "Next" still in the switch's scope? if it is it was after the last statement
|
||||
while (_commentsIt.hasNext()
|
||||
&& !_commentsIt.isNextAfterThisEnds(statement)) {
|
||||
comment = _commentsIt.getNext();
|
||||
_commentsIt.advance();
|
||||
}
|
||||
/*
|
||||
* 'comment' is the last comment found in this case (after the
|
||||
* last statement in this "case"
|
||||
*/
|
||||
checkLastCase(comment);
|
||||
}
|
||||
return super.leave(statement);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* This class's functions...
|
||||
************************************************/
|
||||
public CaseBreakChecker() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statement
|
||||
* @return
|
||||
*/
|
||||
public boolean isBreakOrExitStatement(IASTStatement statement) {
|
||||
CxxAstUtils utils = CxxAstUtils.getInstance();
|
||||
return statement instanceof IASTBreakStatement
|
||||
|| statement instanceof IASTReturnStatement
|
||||
|| statement instanceof IASTContinueStatement
|
||||
|| statement instanceof IASTGotoStatement
|
||||
|| utils.isThrowStatement(statement) || utils.isExitStatement(statement);
|
||||
}
|
||||
|
||||
public void initPreferences(IProblemWorkingCopy problem) {
|
||||
super.initPreferences(problem);
|
||||
addPreference(
|
||||
problem,
|
||||
PARAM_NO_BREAK_COMMENT,
|
||||
CheckersMessages.CaseBreakChecker_DefaultNoBreakCommentDescription,
|
||||
DEFAULT_NO_BREAK_COMMENT);
|
||||
addPreference(problem, PARAM_EMPTY_CASE,
|
||||
CheckersMessages.CaseBreakChecker_EmptyCaseDescription,
|
||||
Boolean.TRUE);
|
||||
addPreference(problem, PARAM_LAST_CASE,
|
||||
CheckersMessages.CaseBreakChecker_LastCaseDescription,
|
||||
Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void processAst(IASTTranslationUnit ast) {
|
||||
_checkLastCase = (Boolean) getPreference(
|
||||
getProblemById(ER_ID, getFile()), PARAM_LAST_CASE);
|
||||
_checkEmptyCase = (Boolean) getPreference(
|
||||
getProblemById(ER_ID, getFile()), PARAM_EMPTY_CASE);
|
||||
_noBreakComment = (String) getPreference(
|
||||
getProblemById(ER_ID, getFile()), PARAM_NO_BREAK_COMMENT);
|
||||
SwitchFindingVisitor visitor = new SwitchFindingVisitor();
|
||||
_commentsIt = new CommentsIterator(ast.getComments());
|
||||
ast.accept(visitor);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,9 @@ import org.eclipse.osgi.util.NLS;
|
|||
*/
|
||||
public class CheckersMessages extends NLS {
|
||||
private static final String BUNDLE_NAME = "org.eclipse.cdt.codan.internal.checkers.messages"; //$NON-NLS-1$
|
||||
public static String CaseBreakChecker_DefaultNoBreakCommentDescription;
|
||||
public static String CaseBreakChecker_EmptyCaseDescription;
|
||||
public static String CaseBreakChecker_LastCaseDescription;
|
||||
public static String CatchByReference_ReportForUnknownType;
|
||||
public static String NamingConventionFunctionChecker_LabelNamePattern;
|
||||
public static String ReturnChecker_Param0;
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
# Contributors:
|
||||
# Alena Laskavaia - initial API and implementation
|
||||
###############################################################################
|
||||
CaseBreakChecker_DefaultNoBreakCommentDescription=Comment text to suppress the problem (regular expression):
|
||||
CaseBreakChecker_EmptyCaseDescription=Check also empty case statement
|
||||
CaseBreakChecker_LastCaseDescription=Check also the last case statement
|
||||
CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved
|
||||
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
||||
ReturnChecker_Param0=Also check functions with implicit return value
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||
|
@ -35,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
|
@ -408,4 +410,30 @@ public final class CxxAstUtils {
|
|||
});
|
||||
return returnSpecifier[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
public boolean isThrowStatement(IASTNode body) {
|
||||
if (!(body instanceof IASTExpressionStatement))
|
||||
return false;
|
||||
IASTExpression expression = ((IASTExpressionStatement) body)
|
||||
.getExpression();
|
||||
if (!(expression instanceof IASTUnaryExpression))
|
||||
return false;
|
||||
return ((IASTUnaryExpression) expression).getOperator() == IASTUnaryExpression.op_throw;
|
||||
}
|
||||
|
||||
public boolean isExitStatement(IASTNode body) {
|
||||
if (!(body instanceof IASTExpressionStatement))
|
||||
return false;
|
||||
IASTExpression expression = ((IASTExpressionStatement) body)
|
||||
.getExpression();
|
||||
if (!(expression instanceof IASTFunctionCallExpression))
|
||||
return false;
|
||||
IASTExpression functionNameExpression = ((IASTFunctionCallExpression) expression)
|
||||
.getFunctionNameExpression();
|
||||
return functionNameExpression.getRawSignature().equals("exit"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,429 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Gil Barash
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Gil Barash - Initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.internal.checkers;
|
||||
|
||||
import org.eclipse.cdt.codan.core.param.IProblemPreference;
|
||||
import org.eclipse.cdt.codan.core.test.CheckerTestCase;
|
||||
import org.eclipse.cdt.codan.internal.checkers.CaseBreakChecker;
|
||||
|
||||
/**
|
||||
* Test for {@link#CaseBreakChecker} class
|
||||
*/
|
||||
public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseBad() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// default:
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseDefaultBad() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// }
|
||||
// }
|
||||
public void testLastCaseBad() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyCaseBad() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseOKbreak() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseWithReturn() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(int a) {
|
||||
// while (a--)
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseWithContinue() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(int a) {
|
||||
//
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// throw 1;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseWithThrow() {
|
||||
loadCodeAndRunCpp(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testLastCaseOKbreak() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// break;
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyCaseOKbreak() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// /* no break */
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseOKcomment() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(int a, int b) {
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// switch (b) {
|
||||
// case 2:
|
||||
// break;
|
||||
// }
|
||||
// case 2:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseTwoSwitches() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// }
|
||||
// }
|
||||
public void testLastCaseOKcomment() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// /* no break */
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// break;
|
||||
// }
|
||||
public void testEmptyCaseOKcomment() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// bye();
|
||||
// }
|
||||
// }
|
||||
public void testLastCaseBadCommentNotLast() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// /*no break*/
|
||||
// case 3:
|
||||
// b = 2;
|
||||
// //no break
|
||||
// case 4:
|
||||
// b = 2;
|
||||
// // no break
|
||||
// case 5:
|
||||
// b = 2;
|
||||
// /* no brea */
|
||||
// case 6:
|
||||
// b = 2;
|
||||
// /* no break1 */
|
||||
// }
|
||||
// }
|
||||
public void testDifferentComments() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(16, 19);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// // lolo
|
||||
// case 2:
|
||||
// case 3:
|
||||
// }
|
||||
//
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// // lolo
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// case 3:
|
||||
// case 4:
|
||||
// break;
|
||||
// case 5:
|
||||
// case 6:
|
||||
// }
|
||||
//
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// // lolo
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// case 3:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// case 4:
|
||||
// b = 2;
|
||||
// case 5:
|
||||
// b = 2;
|
||||
// break;
|
||||
// case 6:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// b = 2;
|
||||
// case 7:
|
||||
// b = 2;
|
||||
// }
|
||||
//
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// // lolo
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// default:
|
||||
// }
|
||||
// }
|
||||
public void testGeneral1() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4, 6, 7, 11, 14, 16, 19, 20, 24, 27, 32, 37, 41, 46,
|
||||
49, 51);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// // lolo
|
||||
// /* no break */
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// // lolo
|
||||
// case 3:
|
||||
// /* no break */
|
||||
// b = 2;
|
||||
// // loo
|
||||
// case 4:
|
||||
// b = 2;
|
||||
// // lolo
|
||||
// /* no break */
|
||||
// case 5:
|
||||
// // lolo
|
||||
// b = 2;
|
||||
// /* no break */
|
||||
// }
|
||||
// }
|
||||
public void testGeneralComments1() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(8, 12);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 0:
|
||||
// switch( b ) {
|
||||
// case 2:
|
||||
// }
|
||||
//
|
||||
// case 1:
|
||||
// switch( b ) {
|
||||
// case 2:
|
||||
// break;
|
||||
// }
|
||||
// case 3:
|
||||
// switch( b ) {
|
||||
// case 2:
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// case 4:
|
||||
// switch( b ) {
|
||||
// case 2:
|
||||
// /* no break */
|
||||
// }
|
||||
// case 5:
|
||||
// switch( b ) {
|
||||
// case 2:
|
||||
// }
|
||||
// /* no break */
|
||||
// }
|
||||
// }
|
||||
public void testNestedSwitches() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4, 6, 9, 20, 27);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// b = 2;
|
||||
// }
|
||||
// }
|
||||
public void testLastCaseIgnore() {
|
||||
setLast(false);
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
setLast(true);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a, b;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// case 2:
|
||||
// b = 2;
|
||||
// break;
|
||||
// case 3: case 4:
|
||||
// b = 2;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
public void testEmptyCaseIgnore() {
|
||||
setEmpty(false);
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
setEmpty(true);
|
||||
}
|
||||
|
||||
// void foo(void) {
|
||||
// int a;
|
||||
// switch( a ) {
|
||||
// case 1:
|
||||
// }
|
||||
// }
|
||||
public void testEmptyLastCaseIgnore() {
|
||||
String code = getAboveComment();
|
||||
setLast(false);
|
||||
loadCodeAndRun(code);
|
||||
checkNoErrors();
|
||||
setLast(true);
|
||||
setEmpty(false);
|
||||
loadCodeAndRun(code);
|
||||
checkNoErrors();
|
||||
setEmpty(true);
|
||||
}
|
||||
|
||||
private void setLast(boolean val) {
|
||||
IProblemPreference pref = getPreference(CaseBreakChecker.ER_ID,
|
||||
CaseBreakChecker.PARAM_LAST_CASE);
|
||||
pref.setValue(val);
|
||||
}
|
||||
|
||||
private void setEmpty(boolean val) {
|
||||
IProblemPreference pref = getPreference(CaseBreakChecker.ER_ID,
|
||||
CaseBreakChecker.PARAM_EMPTY_CASE);
|
||||
pref.setValue(val);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import junit.framework.TestSuite;
|
|||
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.AssignmentInConditionCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.AssignmentToItselfCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.CaseBreakCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.CatchByReferenceTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.ReturnCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.ReturnStyleCheckerTest;
|
||||
|
@ -51,6 +52,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
|
|||
suite.addTestSuite(AssignmentToItselfCheckerTest.class);
|
||||
suite.addTestSuite(ReturnStyleCheckerTest.class);
|
||||
suite.addTestSuite(SuspiciousSemicolonCheckerTest.class);
|
||||
suite.addTestSuite(CaseBreakCheckerTest.class);
|
||||
// framework
|
||||
suite.addTest(CodanFastTestSuite.suite());
|
||||
// quick fixes
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 Alena Laskavaia
|
||||
* Copyright (c) 2009, 2010 Alena Laskavaia
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -27,7 +27,7 @@ import org.eclipse.core.runtime.NullProgressMonitor;
|
|||
|
||||
/**
|
||||
* @author Alena
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CheckerTestCase extends CodanTestCase {
|
||||
protected IMarker[] markers;
|
||||
|
@ -36,6 +36,13 @@ public class CheckerTestCase extends CodanTestCase {
|
|||
return checkErrorLine(currentFile, i);
|
||||
}
|
||||
|
||||
public void checkErrorLines( Object... args ) {
|
||||
for( Object i : args ) {
|
||||
checkErrorLine((Integer) i);
|
||||
}
|
||||
assertEquals(args.length, markers.length);
|
||||
}
|
||||
|
||||
public IMarker checkErrorLine(int i, String problemId) {
|
||||
return checkErrorLine(currentFile, i, problemId);
|
||||
}
|
||||
|
@ -95,7 +102,7 @@ public class CheckerTestCase extends CodanTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void runOnProject() {
|
||||
try {
|
||||
|
@ -117,7 +124,7 @@ public class CheckerTestCase extends CodanTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected void runCodan() {
|
||||
CodanRuntime
|
||||
|
|
Loading…
Add table
Reference in a new issue