1
/*******************************************************************************
2
* Copyright (c) 2009, 2010 Alena Laskavaia
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Alena Laskavaia - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.codan.internal.checkers;
13
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
14
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
15
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
16
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
17
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
18
import org.eclipse.cdt.core.dom.ast.IASTExpression;
19
import org.eclipse.cdt.core.dom.ast.IASTNode;
20
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
21
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
24
* This checker finds a problems which are caused by lack of understanding
26
* precedence in C. In any case it is better to surround expressions in
27
* parenthesis to improve readability. Example: ! x>0 && x<10 (this would be
28
* (!x)>0 && x<10 in C) We only look for &&, || and ! operators (and binary | &
34
public class SuggestedParenthesisChecker extends AbstractIndexAstChecker {
35
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem"; //$NON-NLS-1$
36
public static final String PARAM_NOT = "paramNot"; //$NON-NLS-1$
38
public void processAst(IASTTranslationUnit ast) {
39
// traverse the ast using the visitor pattern.
40
ast.accept(new ExpressionVisitor());
43
class ExpressionVisitor extends ASTVisitor {
45
shouldVisitExpressions = true;
48
public int visit(IASTExpression expression) {
49
int precedence = getPrecedence(expression);
50
IASTNode parent = expression.getParent();
51
if (parent instanceof IASTExpression) {
52
IASTExpression parentExpr = (IASTExpression) parent;
53
if (isInParentesis(expression))
54
return PROCESS_CONTINUE;
55
if (precedence == 2) { // unary not
56
if (isParamNot() && isUsedAsOperand(expression)) {
57
reportProblem(ER_ID, expression, expression.getRawSignature());
60
} else if (precedence >= 0) {
61
int pp = getPrecedence(parentExpr);
62
if (pp == -1 || pp == precedence)
63
return PROCESS_CONTINUE;
64
reportProblem(ER_ID, expression, expression.getRawSignature());
67
return PROCESS_CONTINUE;
70
private boolean isUsedAsOperand(IASTExpression expression) {
71
ASTNodeProperty prop = expression.getPropertyInParent();
72
if (prop == IASTBinaryExpression.OPERAND_ONE
73
// || prop == IASTBinaryExpression.OPERAND_TWO
74
|| prop == IASTUnaryExpression.OPERAND)
80
private int getPrecedence(IASTExpression e) {
81
if (e instanceof IASTBinaryExpression) {
82
IASTBinaryExpression binExpr = (IASTBinaryExpression) e;
83
int operator = binExpr.getOperator();
84
if (operator == IASTBinaryExpression.op_binaryAnd)
86
if (operator == IASTBinaryExpression.op_binaryXor)
88
if (operator == IASTBinaryExpression.op_binaryOr)
90
if (operator == IASTBinaryExpression.op_logicalAnd)
92
if (operator == IASTBinaryExpression.op_logicalOr)
95
if (e instanceof IASTUnaryExpression) {
96
IASTUnaryExpression binExpr = (IASTUnaryExpression) e;
97
int operator = binExpr.getOperator();
98
if (operator == IASTUnaryExpression.op_not)
100
if (operator == IASTUnaryExpression.op_tilde)
110
private boolean isInParentesis(IASTExpression node) {
111
IASTNode parent = node.getParent();
112
if (parent instanceof IASTUnaryExpression) {
113
IASTUnaryExpression br = (IASTUnaryExpression) parent;
114
if (br.getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
121
public boolean isParamNot() {
122
return (Boolean) getPreference(getProblemById(ER_ID, getFile()), PARAM_NOT);
129
* org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences
130
* #initPreferences(org.eclipse.cdt.codan.core.model.IProblemWorkingCopy)
133
public void initPreferences(IProblemWorkingCopy problem) {
134
super.initPreferences(problem);
135
addPreference(problem, PARAM_NOT, CheckersMessages.SuggestedParenthesisChecker_SuggestParanthesesAroundNot, Boolean.FALSE);