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