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 if (location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPreDecrementExpression || location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPreIncrementExpression || location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTPostfixExpression) {
128 return true;
129 }
130
131 if (location.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTStatementExpression) {
132 ASTStatementExpression exp = (ASTStatementExpression) location.jjtGetParent().jjtGetParent().jjtGetParent();
133 if (exp.jjtGetNumChildren() >= 2 && exp.jjtGetChild(1) instanceof ASTAssignmentOperator) {
134 ASTAssignmentOperator op = (ASTAssignmentOperator) exp.jjtGetChild(1);
135 if (op.isCompound()) {
136 return true;
137 }
138 }
139 }
140 return false;
141 }
142
143 public boolean isThisOrSuper() {
144 return image.equals("this") || image.equals("super");
145 }
146
147 public boolean equals(Object o) {
148 NameOccurrence n = (NameOccurrence) o;
149 return n.getImage().equals(getImage());
150 }
151
152 public int hashCode() {
153 return getImage().hashCode();
154 }
155
156 public String getImage() {
157 return image;
158 }
159
160 public String toString() {
161 return getImage() + ":" + location.getBeginLine() + ":" + location.getClass() + (this.isMethodOrConstructorInvocation() ? "(method call)" : "");
162 }
163 }