From ea005007255a5b00d2324ddec07f9f46d8e2df60 Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Mon, 18 Oct 2010 01:18:49 +0000 Subject: [PATCH] Bug 322119 - [checker] Suspicious semicolon (i.e. ";" after "if") --- .../OSGI-INF/l10n/bundle.properties | 6 +- .../org.eclipse.cdt.codan.checkers/plugin.xml | 18 ++- .../checkers/SuspiciousSemicolonChecker.java | 57 +++++++ .../SuspiciousSemicolonCheckerTest.java | 153 ++++++++++++++++++ .../core/test/AutomatedIntegrationSuite.java | 2 + 5 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java create mode 100644 codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java diff --git a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties index de98893a7c7..f81a2b13c43 100644 --- a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties +++ b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties @@ -52,4 +52,8 @@ problem.description.AssignmentToItself = Finds expression where left and right s checker.name.ReturnStyle = Return with parenthesis problem.name.ReturnStyle = Return with parenthesis problem.messagePattern.ReturnStyle = Return statement has invalid style. Return value should be surrounded by parenthesis -problem.description.ReturnStyle = Checks for return statements that do no return the value in parenthesis. For example 'return 0;' \ No newline at end of file +problem.description.ReturnStyle = Checks for return statements that do no return the value in parenthesis. For example 'return 0;' +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);' \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml index 409cb9a7781..ab87727a4e6 100644 --- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml +++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml @@ -278,7 +278,7 @@ name="%problem.name.AssignmentToItself"> - @@ -291,6 +291,20 @@ messagePattern="%problem.messagePattern.ReturnStyle" name="%problem.name.ReturnStyle"> - + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java new file mode 100644 index 00000000000..3ea61391943 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2010 Marc-Andre Laperle and others. + * 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: + * Marc-Andre Laperle - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +import org.eclipse.cdt.core.dom.ast.IASTNullStatement; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; + +public class SuspiciousSemicolonChecker extends AbstractIndexAstChecker { + private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { + ast.accept(new ASTVisitor() { + { + shouldVisitStatements = true; + } + + @Override + public int visit(IASTStatement statement) { + if (statement instanceof IASTIfStatement) { + IASTStatement thenStmt = ((IASTIfStatement) statement) + .getThenClause(); + if (thenStmt instanceof IASTNullStatement + && noMacroInvolved(thenStmt)) { + reportProblem(ER_ID, thenStmt, (Object) null); + } + } + return PROCESS_CONTINUE; + } + }); + } + + + protected boolean noMacroInvolved(IASTStatement node) { + IASTNodeSelector nodeSelector = node.getTranslationUnit() + .getNodeSelector(node.getTranslationUnit().getFilePath()); + IASTFileLocation fileLocation = node.getFileLocation(); + IASTPreprocessorMacroExpansion macro = nodeSelector + .findEnclosingMacroExpansion(fileLocation.getNodeOffset() - 1, + 1); + return macro == null; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java new file mode 100644 index 00000000000..ee0b9bf82a9 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2010 Marc-Andre Laperle and others. + * 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: + * Marc-Andre Laperle - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.test.CheckerTestCase; + +public class SuspiciousSemicolonCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems("org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"); //$NON-NLS-1$ + } + + // void foo() { + // if(0); + // } + public void testIf1() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0); + // { + // } + // } + public void testIf2() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0) + // foo(); + // } + public void testIf3() { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // if(0) + // ; + // } + public void testIf4() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0);{ + // } + // } + public void testIf5() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0) {}; + // } + public void testIf6() { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // if(0 + // ); + // } + // } + public void testIf7() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0) + // ; + // else if(0); + // } + public void testElseIf1() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0); + // { + // + // } + // } + public void testElseIf2() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0);{ + // } + // } + public void testElseIf3() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0){}; + // } + public void testElseIf4() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0) + // ; + // else if(0 + // ); + // } + public void testElseIf5() { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(5); + } + + // #define OP + // void foo() { + // if(0) + // OP; + // } + public void testMacro() { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java index 30d9292f6d2..119eece8c9c 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.codan.core.internal.checkers.ReturnCheckerTest; import org.eclipse.cdt.codan.core.internal.checkers.ReturnStyleCheckerTest; import org.eclipse.cdt.codan.core.internal.checkers.StatementHasNoEffectCheckerTest; import org.eclipse.cdt.codan.core.internal.checkers.SuggestedParenthesisCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.SuspiciousSemicolonCheckerTest; import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.SuggestedParenthesisQuickFixTest; public class AutomatedIntegrationSuite extends TestSuite { @@ -49,6 +50,7 @@ public class AutomatedIntegrationSuite extends TestSuite { suite.addTestSuite(AssignmentInConditionCheckerTest.class); suite.addTestSuite(AssignmentToItselfCheckerTest.class); suite.addTestSuite(ReturnStyleCheckerTest.class); + suite.addTestSuite(SuspiciousSemicolonCheckerTest.class); // framework suite.addTest(CodanFastTestSuite.suite()); // quick fixes