/*******************************************************************************
* Copyright (c) 2010, 2012 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
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers;
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
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 {
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"; //$NON-NLS-1$
public static final String PARAM_ELSE = "else"; //$NON-NLS-1$
public static final String PARAM_ALFTER_ELSE = "afterelse"; //$NON-NLS-1$
@Override
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();
IASTStatement elseStmt = ((IASTIfStatement) statement).getElseClause();
if (elseStmt instanceof IASTNullStatement && doReportAfterElse() &&
!macroInvolved(elseStmt)) {
reportProblem(ER_ID, elseStmt);
}
if (elseStmt != null && doNotReportIfElse())
return PROCESS_CONTINUE;
if (thenStmt instanceof IASTNullStatement && !macroInvolved(thenStmt)) {
reportProblem(ER_ID, thenStmt);
}
}
return PROCESS_CONTINUE;
}
});
}
private boolean doNotReportIfElse() {
final IProblem pt = getProblemById(ER_ID, getFile());
return (Boolean) getPreference(pt, PARAM_ELSE);
}
private boolean doReportAfterElse() {
final IProblem pt = getProblemById(ER_ID, getFile());
return (Boolean) getPreference(pt, PARAM_ALFTER_ELSE);
}
private static boolean macroInvolved(IASTStatement node) {
if (includesMacroExpansion(node)) {
return true;
}
IASTNodeSelector nodeSelector = node.getTranslationUnit().getNodeSelector(node.getTranslationUnit().getFilePath());
IASTFileLocation fileLocation = node.getFileLocation();
IASTPreprocessorMacroExpansion macro = nodeSelector.findEnclosingMacroExpansion(fileLocation.getNodeOffset() - 1, 1);
return macro != null;
}
@Override
public void initPreferences(IProblemWorkingCopy problem) {
super.initPreferences(problem);
addPreference(problem, PARAM_ELSE, CheckersMessages.SuspiciousSemicolonChecker_ParamElse, Boolean.FALSE);
addPreference(problem, PARAM_ALFTER_ELSE, CheckersMessages.SuspiciousSemicolonChecker_ParamAfterElse, Boolean.FALSE);
}
}