mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 333813 - fixed fp, default settings and description
This commit is contained in:
parent
5f895da197
commit
db436ae417
5 changed files with 113 additions and 54 deletions
|
@ -58,5 +58,5 @@ problem.name.SuspiciousSemicolon = Suspicious semicolon
|
||||||
problem.messagePattern.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
|
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.description.CaseBreak = Looks for "case" statements which end without a "break" statement
|
||||||
problem.messagePattern.CaseBreak = No break at the end of this case
|
problem.messagePattern.CaseBreak = No break at the end of this case
|
|
@ -130,62 +130,72 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements
|
||||||
* "switch"s
|
* "switch"s
|
||||||
*/
|
*/
|
||||||
class SwitchVisitor extends SwitchFindingVisitor {
|
class SwitchVisitor extends SwitchFindingVisitor {
|
||||||
private IASTStatement _last_case_stmnt;
|
private IASTStatement _prev_case_stmnt;
|
||||||
private boolean _first_case_statement;
|
private boolean _first_case_statement;
|
||||||
private int _last_break_stmnt_offset;
|
private int _prev_break_stmnt_offset;
|
||||||
private int _last_normal_stmnt_offset;
|
private int _prev_normal_stmnt_offset;
|
||||||
private int _last_case_stmnt_offset;
|
private int _prev_case_stmnt_offset;
|
||||||
|
|
||||||
SwitchVisitor(IASTStatement switch_statement) {
|
SwitchVisitor(IASTStatement switch_statement) {
|
||||||
shouldVisitStatements = true;
|
shouldVisitStatements = true;
|
||||||
_first_case_statement = true;
|
_first_case_statement = true;
|
||||||
_switchStatement = switch_statement;
|
_switchStatement = switch_statement;
|
||||||
_last_break_stmnt_offset = 0;
|
_prev_break_stmnt_offset = 0;
|
||||||
_last_normal_stmnt_offset = 0;
|
_prev_normal_stmnt_offset = 0;
|
||||||
_last_case_stmnt_offset = 0;
|
_prev_case_stmnt_offset = 0;
|
||||||
_last_case_stmnt = null;
|
_prev_case_stmnt = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Is this an "empty" case (i.e. with no statements in it)
|
* @return Is this an "empty" case (i.e. with no statements in it)
|
||||||
*/
|
*/
|
||||||
private boolean isEmptyCase() {
|
private boolean isEmptyCase() {
|
||||||
return _last_case_stmnt_offset > _last_normal_stmnt_offset;
|
return _prev_case_stmnt_offset > _prev_normal_stmnt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Was a "break" statement the last statement in this case
|
* @return Was a "break" statement the last statement in this case
|
||||||
*/
|
*/
|
||||||
private boolean breakFoundLast() {
|
private boolean breakFoundPrevious() {
|
||||||
return _last_normal_stmnt_offset < _last_break_stmnt_offset
|
return _prev_normal_stmnt_offset < _prev_break_stmnt_offset
|
||||||
&& _last_case_stmnt_offset < _last_break_stmnt_offset;
|
&& _prev_case_stmnt_offset < _prev_break_stmnt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the last case we've visited
|
* Check the last case we've visited
|
||||||
*
|
*
|
||||||
* @param comment The comment ending this case (may be NULL)
|
* @param comment The comment ending this case (may be NULL)
|
||||||
|
* @param lastOne true if it am actual Last statement
|
||||||
*/
|
*/
|
||||||
private void checkLastCase(IASTComment comment) {
|
private void checkPreviousCase(IASTComment comment, boolean lastOne) {
|
||||||
if (comment != null) {
|
if (comment != null) {
|
||||||
String str = new String(comment.getComment());
|
String str = getTrimmedComment(comment);
|
||||||
if (comment.isBlockComment())
|
|
||||||
str = str.substring(2, str.length() - 2);
|
|
||||||
else
|
|
||||||
str = str.substring(2);
|
|
||||||
str = str.trim();
|
|
||||||
if (str.equalsIgnoreCase(_noBreakComment))
|
if (str.equalsIgnoreCase(_noBreakComment))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_last_case_stmnt == null)
|
if (_prev_case_stmnt == null)
|
||||||
return; // This is an empty switch
|
return; // This is an empty switch
|
||||||
if (breakFoundLast())
|
if (breakFoundPrevious())
|
||||||
return; // There was a "break" before the current statement
|
return; // There was a "break" before the current statement
|
||||||
if (!isEmptyCase() || _checkEmptyCase) {
|
if (lastOne == true || !isEmptyCase() || _checkEmptyCase) {
|
||||||
reportProblem(ER_ID, _last_case_stmnt, (Object) null);
|
reportProblem(ER_ID, _prev_case_stmnt, (Object) null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param comment
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getTrimmedComment(IASTComment comment) {
|
||||||
|
String str = new String(comment.getComment());
|
||||||
|
if (comment.isBlockComment())
|
||||||
|
str = str.substring(2, str.length() - 2);
|
||||||
|
else
|
||||||
|
str = str.substring(2);
|
||||||
|
str = str.trim();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int visit(IASTStatement statement) {
|
public int visit(IASTStatement statement) {
|
||||||
if (statement instanceof IASTCaseStatement
|
if (statement instanceof IASTCaseStatement
|
||||||
|
@ -213,17 +223,17 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements
|
||||||
* 'comment' is the last comment found in this case (after
|
* 'comment' is the last comment found in this case (after
|
||||||
* the last statement in this "case"
|
* the last statement in this "case"
|
||||||
*/
|
*/
|
||||||
checkLastCase(comment);
|
checkPreviousCase(comment, false);
|
||||||
}
|
}
|
||||||
/* Update variables with the new opened "case" */
|
/* Update variables with the new opened "case" */
|
||||||
_last_case_stmnt_offset = statement.getFileLocation()
|
_prev_case_stmnt_offset = statement.getFileLocation()
|
||||||
.getNodeOffset();
|
.getNodeOffset();
|
||||||
_last_case_stmnt = statement;
|
_prev_case_stmnt = statement;
|
||||||
} else if (isBreakOrExitStatement(statement)) { // A "break" statement
|
} else if (isBreakOrExitStatement(statement)) { // A "break" statement
|
||||||
_last_break_stmnt_offset = statement.getFileLocation()
|
_prev_break_stmnt_offset = statement.getFileLocation()
|
||||||
.getNodeOffset();
|
.getNodeOffset();
|
||||||
} else { // a non-switch related statement
|
} else { // a non-switch related statement
|
||||||
_last_normal_stmnt_offset = statement.getFileLocation()
|
_prev_normal_stmnt_offset = statement.getFileLocation()
|
||||||
.getNodeOffset();
|
.getNodeOffset();
|
||||||
}
|
}
|
||||||
/* advance comments we already passed */
|
/* advance comments we already passed */
|
||||||
|
@ -252,7 +262,7 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements
|
||||||
* 'comment' is the last comment found in this case (after the
|
* 'comment' is the last comment found in this case (after the
|
||||||
* last statement in this "case"
|
* last statement in this "case"
|
||||||
*/
|
*/
|
||||||
checkLastCase(comment);
|
checkPreviousCase(comment, true);
|
||||||
}
|
}
|
||||||
return super.leave(statement);
|
return super.leave(statement);
|
||||||
}
|
}
|
||||||
|
@ -284,12 +294,13 @@ public class CaseBreakChecker extends AbstractIndexAstChecker implements
|
||||||
PARAM_NO_BREAK_COMMENT,
|
PARAM_NO_BREAK_COMMENT,
|
||||||
CheckersMessages.CaseBreakChecker_DefaultNoBreakCommentDescription,
|
CheckersMessages.CaseBreakChecker_DefaultNoBreakCommentDescription,
|
||||||
DEFAULT_NO_BREAK_COMMENT);
|
DEFAULT_NO_BREAK_COMMENT);
|
||||||
addPreference(problem, PARAM_EMPTY_CASE,
|
|
||||||
CheckersMessages.CaseBreakChecker_EmptyCaseDescription,
|
|
||||||
Boolean.TRUE);
|
|
||||||
addPreference(problem, PARAM_LAST_CASE,
|
addPreference(problem, PARAM_LAST_CASE,
|
||||||
CheckersMessages.CaseBreakChecker_LastCaseDescription,
|
CheckersMessages.CaseBreakChecker_LastCaseDescription,
|
||||||
Boolean.TRUE);
|
Boolean.TRUE);
|
||||||
|
addPreference(problem, PARAM_EMPTY_CASE,
|
||||||
|
CheckersMessages.CaseBreakChecker_EmptyCaseDescription,
|
||||||
|
Boolean.FALSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processAst(IASTTranslationUnit ast) {
|
public void processAst(IASTTranslationUnit ast) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
# Alena Laskavaia - initial API and implementation
|
# Alena Laskavaia - initial API and implementation
|
||||||
###############################################################################
|
###############################################################################
|
||||||
CaseBreakChecker_DefaultNoBreakCommentDescription=Comment text to suppress the problem (regular expression):
|
CaseBreakChecker_DefaultNoBreakCommentDescription=Comment text to suppress the problem (regular expression):
|
||||||
CaseBreakChecker_EmptyCaseDescription=Check also empty case statement
|
CaseBreakChecker_EmptyCaseDescription=Check also empty case statement (except if last)
|
||||||
CaseBreakChecker_LastCaseDescription=Check also the last case statement
|
CaseBreakChecker_LastCaseDescription=Check also the last case statement
|
||||||
CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved
|
CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved
|
||||||
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
||||||
|
|
|
@ -18,6 +18,19 @@ import org.eclipse.cdt.codan.internal.checkers.CaseBreakChecker;
|
||||||
* Test for {@link#CaseBreakChecker} class
|
* Test for {@link#CaseBreakChecker} class
|
||||||
*/
|
*/
|
||||||
public class CaseBreakCheckerTest extends CheckerTestCase {
|
public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.eclipse.cdt.codan.core.test.CodanTestCase#setUp()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
// set default prefs
|
||||||
|
setEmpty(false);
|
||||||
|
setLast(true);
|
||||||
|
}
|
||||||
|
|
||||||
// void foo(void) {
|
// void foo(void) {
|
||||||
// int a;
|
// int a;
|
||||||
// switch( a ) {
|
// switch( a ) {
|
||||||
|
@ -62,6 +75,7 @@ public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
public void testEmptyCaseBad() {
|
public void testEmptyCaseBad() {
|
||||||
|
setEmpty(true);
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(4);
|
checkErrorLines(4);
|
||||||
}
|
}
|
||||||
|
@ -293,6 +307,7 @@ public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
public void testGeneral1() {
|
public void testGeneral1() {
|
||||||
|
setEmpty(true);
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(4, 6, 7, 11, 14, 16, 19, 20, 24, 27, 32, 37, 41, 46,
|
checkErrorLines(4, 6, 7, 11, 14, 16, 19, 20, 24, 27, 32, 37, 41, 46,
|
||||||
49, 51);
|
49, 51);
|
||||||
|
@ -394,7 +409,6 @@ public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
setEmpty(false);
|
setEmpty(false);
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
setEmpty(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void foo(void) {
|
// void foo(void) {
|
||||||
|
@ -411,8 +425,7 @@ public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
setLast(true);
|
setLast(true);
|
||||||
setEmpty(false);
|
setEmpty(false);
|
||||||
loadCodeAndRun(code);
|
loadCodeAndRun(code);
|
||||||
checkNoErrors();
|
checkErrorLine(4);
|
||||||
setEmpty(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLast(boolean val) {
|
private void setLast(boolean val) {
|
||||||
|
@ -439,4 +452,23 @@ public class CaseBreakCheckerTest extends CheckerTestCase {
|
||||||
checkNoErrors(); // FALSE NEGATIVE
|
checkNoErrors(); // FALSE NEGATIVE
|
||||||
//checkErrorLine(3);
|
//checkErrorLine(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void foo(void) {
|
||||||
|
// int a;
|
||||||
|
// switch( a ) {
|
||||||
|
// case 2:
|
||||||
|
// break;
|
||||||
|
// case 1:
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void testEmptyLastCaseError() {
|
||||||
|
String code = getAboveComment();
|
||||||
|
setLast(true);
|
||||||
|
setEmpty(false);
|
||||||
|
loadCodeAndRun(code);
|
||||||
|
checkErrorLine(6);
|
||||||
|
setLast(false);
|
||||||
|
loadCodeAndRun(code);
|
||||||
|
checkNoErrors();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alena
|
* @author Alena
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CheckerTestCase extends CodanTestCase {
|
public class CheckerTestCase extends CodanTestCase {
|
||||||
protected IMarker[] markers;
|
protected IMarker[] markers;
|
||||||
|
@ -36,8 +36,8 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
return checkErrorLine(currentFile, i);
|
return checkErrorLine(currentFile, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkErrorLines( Object... args ) {
|
public void checkErrorLines(Object... args) {
|
||||||
for( Object i : args ) {
|
for (Object i : args) {
|
||||||
checkErrorLine((Integer) i);
|
checkErrorLine((Integer) i);
|
||||||
}
|
}
|
||||||
assertEquals(args.length, markers.length);
|
assertEquals(args.length, markers.length);
|
||||||
|
@ -65,18 +65,7 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
IMarker m = null;
|
IMarker m = null;
|
||||||
for (int j = 0; j < markers.length; j++) {
|
for (int j = 0; j < markers.length; j++) {
|
||||||
m = markers[j];
|
m = markers[j];
|
||||||
Object pos;
|
line = getLine(m);
|
||||||
try {
|
|
||||||
line = (Integer) m.getAttribute(IMarker.LINE_NUMBER);
|
|
||||||
if (line == null || line.equals(-1)) {
|
|
||||||
pos = m.getAttribute(IMarker.CHAR_START);
|
|
||||||
line = new Integer(pos2line(((Integer) pos).intValue()));
|
|
||||||
}
|
|
||||||
} catch (CoreException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
mfile = m.getResource().getName();
|
mfile = m.getResource().getName();
|
||||||
if (line.equals(expectedLine)
|
if (line.equals(expectedLine)
|
||||||
&& (problemId == null || problemId
|
&& (problemId == null || problemId
|
||||||
|
@ -96,9 +85,36 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param line
|
||||||
|
* @param m
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Integer getLine(IMarker m) {
|
||||||
|
Integer line = null;
|
||||||
|
try {
|
||||||
|
line = (Integer) m.getAttribute(IMarker.LINE_NUMBER);
|
||||||
|
if (line == null || line.equals(-1)) {
|
||||||
|
Object pos = m.getAttribute(IMarker.CHAR_START);
|
||||||
|
line = new Integer(pos2line(((Integer) pos).intValue()));
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
public void checkNoErrors() {
|
public void checkNoErrors() {
|
||||||
assertTrue("Found errors but should not", markers == null
|
if (markers == null || markers.length == 0) {
|
||||||
|| markers.length == 0);
|
// all good
|
||||||
|
} else {
|
||||||
|
IMarker m = markers[0];
|
||||||
|
fail("Found " + markers.length + " errors but should not. First "
|
||||||
|
+ CodanProblemMarker.getProblemId(m) + " at line "
|
||||||
|
+ getLine(m));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue