1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.symboltable;
5
6 import net.sourceforge.pmd.IPositionProvider;
7 import net.sourceforge.pmd.ast.ASTAssignmentOperator;
8 import net.sourceforge.pmd.ast.ASTExpression;
9 import net.sourceforge.pmd.ast.ASTName;
10 import net.sourceforge.pmd.ast.ASTPostfixExpression;
11 import net.sourceforge.pmd.ast.ASTPreDecrementExpression;
12 import net.sourceforge.pmd.ast.ASTPreIncrementExpression;
13 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
14 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
15 import net.sourceforge.pmd.ast.ASTStatementExpression;
16 import net.sourceforge.pmd.ast.Node;
17 import net.sourceforge.pmd.ast.SimpleNode;
18
19 public class NameOccurrence implements IPositionProvider {
20
21 private SimpleNode location;
22 private String image;
23 private NameOccurrence qualifiedName;
24 private boolean isMethodOrConstructorInvocation;
25
26 public NameOccurrence(SimpleNode location, String image) {
27 this.location = location;
28 this.image = image;
29 }
30
31 public void setIsMethodOrConstructorInvocation() {
32 isMethodOrConstructorInvocation = true;
33 }
34
35 public boolean isMethodOrConstructorInvocation() {
36 return isMethodOrConstructorInvocation;
37 }
38
39 public void setNameWhichThisQualifies(NameOccurrence qualifiedName) {
40 this.qualifiedName = qualifiedName;
41 }
42
43 public NameOccurrence getNameForWhichThisIsAQualifier() {
44 return qualifiedName;
45 }
46
47 public boolean isPartOfQualifiedName() {
48 return qualifiedName != null;
49 }
50
51 public SimpleNode getLocation() {
52 return location;
53 }
54
55 public boolean isOnRightHandSide() {
56 SimpleNode node = (SimpleNode) location.jjtGetParent().jjtGetParent().jjtGetParent();
57 return node instanceof ASTExpression && node.jjtGetNumChildren() == 3;
58 }
59
60 public boolean isOnLeftHandSide() {
61 SimpleNode primaryExpression;
62 if (location.jjtGetParent() instanceof ASTPrimaryExpression) {
63 primaryExpression = (SimpleNode) location.jjtGetParent().jjtGetParent();
64 } else if (location.jjtGetParent().jjtGetParent() instanceof ASTPrimaryExpression) {
65 primaryExpression = (SimpleNode) location.jjtGetParent().jjtGetParent().jjtGetParent();
66 } else {
67 throw new RuntimeException("Found a NameOccurrence that didn't have an ASTPrimary Expression as parent or grandparent. Parent = " + location.jjtGetParent() + " and grandparent = " + location.jjtGetParent().jjtGetParent());
68 }
69
70 if (isStandAlonePostfix(primaryExpression)) {
71 return true;
72 }
73
74 if (primaryExpression.jjtGetNumChildren() <= 1) {
75 return false;
76 }
77
78 if (!(primaryExpression.jjtGetChild(1) instanceof ASTAssignmentOperator)) {
79 return false;
80 }
81
82 if (isPartOfQualifiedName()
83 return false;
84 }
85
86 if (isCompoundAssignment(primaryExpression)) {
87 return false;
88 }
89
90 return true;
91 }
92
93 private boolean isCompoundAssignment(SimpleNode primaryExpression) {
94 return ((ASTAssignmentOperator) (primaryExpression.jjtGetChild(1))).isCompound();
95 }
96
97 private boolean isStandAlonePostfix(SimpleNode primaryExpression) {
98 if (!(primaryExpression instanceof ASTPostfixExpression) || !(primaryExpression.jjtGetParent() instanceof ASTStatementExpression)) {
99 return false;
100 }
101
102 ASTPrimaryPrefix pf = (ASTPrimaryPrefix)((ASTPrimaryExpression)primaryExpression.jjtGetChild(0)).jjtGetChild(0);
103 if (pf.usesThisModifier()) {
104 return true;
105 }
106
107 return thirdChildHasDottedName(primaryExpression);
108 }
109
110 private boolean thirdChildHasDottedName(SimpleNode primaryExpression) {
111 Node thirdChild = primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0);
112 return thirdChild instanceof ASTName && ((ASTName)thirdChild).getImage().indexOf(".") == -1;
113 }
114
115 public boolean isSelfAssignment() {
116 if (location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPreDecrementExpression || location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPreIncrementExpression || location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPostfixExpression) {
117 return true;
118 }
119
120 if (location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTStatementExpression) {
121 ASTStatementExpression exp = (ASTStatementExpression)location.jjtGetParent().jjtGetParent().jjtGetParent();
122 if (exp.jjtGetNumChildren() >= 2 && exp.jjtGetChild(1) instanceof ASTAssignmentOperator) {
123 ASTAssignmentOperator op = (ASTAssignmentOperator)exp.jjtGetChild(1);
124 if (op.isCompound()) {
125 return true;
126 }
127 }
128 }
129 return false;
130 }
131
132 public Scope getScope() {
133 return location.getScope();
134 }
135
136 public int getBeginLine() {
137 return location.getBeginLine();
138 }
139
140 public boolean isThisOrSuper() {
141 return image.equals("this") || image.equals("super");
142 }
143
144 public boolean equals(Object o) {
145 NameOccurrence n = (NameOccurrence) o;
146 return n.getImage().equals(getImage());
147 }
148
149 public String getImage() {
150 return image;
151 }
152
153 public int hashCode() {
154 return getImage().hashCode();
155 }
156
157 public String toString() {
158 return getImage() + ":" + location.getBeginLine() + ":" + location.getClass();
159 }
160
161 /***
162 * @see net.sourceforge.pmd.IPositionProvider#getEndLine()
163 */
164 public int getEndLine() {
165 return location.getEndLine();
166 }
167
168 /***
169 * @see net.sourceforge.pmd.IPositionProvider#getBeginColumn()
170 */
171 public int getBeginColumn() {
172 return location.getBeginColumn();
173 }
174
175 /***
176 * @see net.sourceforge.pmd.IPositionProvider#getEndColumn()
177 */
178 public int getEndColumn() {
179 return location.getEndColumn();
180 }
181
182 }