1
2
3
4 package net.sourceforge.pmd.lang.java.symboltable;
5
6 import net.sourceforge.pmd.lang.ast.Node;
7 import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
8 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
9 import net.sourceforge.pmd.lang.java.ast.ASTMethodReference;
10 import net.sourceforge.pmd.lang.java.ast.ASTName;
11 import net.sourceforge.pmd.lang.java.ast.ASTPostfixExpression;
12 import net.sourceforge.pmd.lang.java.ast.ASTPreDecrementExpression;
13 import net.sourceforge.pmd.lang.java.ast.ASTPreIncrementExpression;
14 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
15 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
16 import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
17 import net.sourceforge.pmd.lang.java.ast.JavaNode;
18 import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
19
20 public class JavaNameOccurrence implements NameOccurrence {
21
22 private JavaNode location;
23 private String image;
24 private NameOccurrence qualifiedName;
25
26 private boolean isMethodOrConstructorInvocation;
27 private int argumentCount;
28
29 private final static String THIS = "this";
30 private final static String SUPER = "super";
31
32 private final static String THIS_DOT = "this.";
33 private final static String SUPER_DOT = "super.";
34
35 public JavaNameOccurrence(JavaNode location, String image) {
36 this.location = location;
37 this.image = image;
38 }
39
40 public void setIsMethodOrConstructorInvocation() {
41 isMethodOrConstructorInvocation = true;
42 }
43
44 public void setArgumentCount(int count) {
45 argumentCount = count;
46 }
47
48 public int getArgumentCount() {
49 return argumentCount;
50 }
51
52 public boolean isMethodOrConstructorInvocation() {
53 return isMethodOrConstructorInvocation;
54 }
55 public boolean isMethodReference() {
56 return location instanceof ASTMethodReference;
57 }
58
59 public void setNameWhichThisQualifies(NameOccurrence qualifiedName) {
60 this.qualifiedName = qualifiedName;
61 }
62
63 public NameOccurrence getNameForWhichThisIsAQualifier() {
64 return qualifiedName;
65 }
66
67 public boolean isPartOfQualifiedName() {
68 return qualifiedName != null;
69 }
70
71 public JavaNode getLocation() {
72 return location;
73 }
74
75 public boolean isOnRightHandSide() {
76 Node node = location.jjtGetParent().jjtGetParent().jjtGetParent();
77 return node instanceof ASTExpression && node.jjtGetNumChildren() == 3;
78 }
79
80
81 public boolean isOnLeftHandSide() {
82
83 Node primaryExpression;
84 if (location.jjtGetParent() instanceof ASTPrimaryExpression) {
85 primaryExpression = location.jjtGetParent().jjtGetParent();
86 } else if (location.jjtGetParent().jjtGetParent() instanceof ASTPrimaryExpression) {
87 primaryExpression = location.jjtGetParent().jjtGetParent().jjtGetParent();
88 } else {
89 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());
90 }
91
92 if (isStandAlonePostfix(primaryExpression)) {
93 return true;
94 }
95
96 if (primaryExpression.jjtGetNumChildren() <= 1) {
97 return false;
98 }
99
100 if (!(primaryExpression.jjtGetChild(1) instanceof ASTAssignmentOperator)) {
101 return false;
102 }
103
104 if (isPartOfQualifiedName() ) {
105 return false;
106 }
107
108 if (isCompoundAssignment(primaryExpression)) {
109 return false;
110 }
111
112 return true;
113 }
114
115 private boolean isCompoundAssignment(Node primaryExpression) {
116 return ((ASTAssignmentOperator) primaryExpression.jjtGetChild(1)).isCompound();
117 }
118
119 private boolean isStandAlonePostfix(Node primaryExpression) {
120 if (!(primaryExpression instanceof ASTPostfixExpression) || !(primaryExpression.jjtGetParent() instanceof ASTStatementExpression)) {
121 return false;
122 }
123
124 ASTPrimaryPrefix pf = (ASTPrimaryPrefix) ((ASTPrimaryExpression) primaryExpression.jjtGetChild(0)).jjtGetChild(0);
125 if (pf.usesThisModifier()) {
126 return true;
127 }
128
129 return thirdChildHasDottedName(primaryExpression);
130 }
131
132 private boolean thirdChildHasDottedName(Node primaryExpression) {
133 Node thirdChild = primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0);
134 return thirdChild instanceof ASTName && ((ASTName) thirdChild).getImage().indexOf('.') == -1;
135 }
136
137
138
139
140
141
142
143
144
145 @SuppressWarnings("PMD.AvoidBranchingStatementAsLastInLoop")
146 public boolean isSelfAssignment() {
147 Node l = location;
148 while (true) {
149 Node p = l.jjtGetParent();
150 Node gp = p.jjtGetParent();
151 Node node = gp.jjtGetParent();
152 if (node instanceof ASTPreDecrementExpression || node instanceof ASTPreIncrementExpression || node instanceof ASTPostfixExpression) {
153 return true;
154 }
155
156 if (hasAssignmentOperator(gp)) {
157 return isCompoundAssignment(gp);
158 }
159
160 if (hasAssignmentOperator(node)) {
161 return isCompoundAssignment(node);
162 }
163
164
165 if (p instanceof ASTPrimaryPrefix && p.jjtGetNumChildren() == 1 &&
166 gp instanceof ASTPrimaryExpression && gp.jjtGetNumChildren() == 1&&
167 node instanceof ASTExpression && node.jjtGetNumChildren() == 1 &&
168 node.jjtGetParent() instanceof ASTPrimaryPrefix && node.jjtGetParent().jjtGetNumChildren() == 1) {
169 l = node;
170 continue;
171 }
172
173
174 return gp instanceof ASTPreDecrementExpression || gp instanceof ASTPreIncrementExpression || gp instanceof ASTPostfixExpression;
175 }
176 }
177
178 private boolean hasAssignmentOperator(Node node) {
179 if (node instanceof ASTStatementExpression || node instanceof ASTExpression) {
180 if (node.jjtGetNumChildren() >= 2 && node.jjtGetChild(1) instanceof ASTAssignmentOperator) {
181 return true;
182 }
183 }
184 return false;
185 }
186
187
188
189
190
191
192 public boolean isThisOrSuper() {
193 return image != null && (image.equals(THIS) || image.equals(SUPER));
194 }
195
196
197
198
199
200
201 public boolean useThisOrSuper() {
202 Node node = location.jjtGetParent();
203 if ( node instanceof ASTPrimaryExpression ) {
204 ASTPrimaryExpression primaryExpression = (ASTPrimaryExpression)node;
205 ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) primaryExpression.jjtGetChild(0);
206 if ( prefix != null ) {
207 return prefix.usesSuperModifier() || prefix.usesThisModifier();
208 }
209 }
210 return image.startsWith(THIS_DOT) || image.startsWith(SUPER_DOT);
211 }
212
213 @Override
214 public boolean equals(Object o) {
215 if (o instanceof JavaNameOccurrence) {
216 JavaNameOccurrence n = (JavaNameOccurrence) o;
217 return n.getImage().equals(getImage());
218 }
219 return false;
220 }
221
222 @Override
223 public int hashCode() {
224 return getImage().hashCode();
225 }
226
227 public String getImage() {
228 return image;
229 }
230
231 @Override
232 public String toString() {
233 return getImage() + ":" + location.getBeginLine() + ":" + location.getClass() + (this.isMethodOrConstructorInvocation() ? "(method call)" : "");
234 }
235 }