1 /**
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.lang.plsql.symboltable;
5
6 import net.sourceforge.pmd.lang.ast.Node;
7 import net.sourceforge.pmd.lang.plsql.ast.ASTExpression;
8 import net.sourceforge.pmd.lang.plsql.ast.ASTPrimaryExpression;
9 import net.sourceforge.pmd.lang.plsql.ast.PLSQLNode;
10 import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
11
12 public class PLSQLNameOccurrence implements NameOccurrence {
13
14 private PLSQLNode location;
15 private String image;
16 private PLSQLNameOccurrence qualifiedName;
17
18 private boolean isMethodOrConstructorInvocation;
19 private int argumentCount;
20
21 private final static String THIS = "this";
22 private final static String SUPER = "super";
23
24 public PLSQLNameOccurrence(PLSQLNode location, String image) {
25 this.location = location;
26 this.image = image;
27 }
28
29 public void setIsMethodOrConstructorInvocation() {
30 isMethodOrConstructorInvocation = true;
31 }
32
33 public void setArgumentCount(int count) {
34 argumentCount = count;
35 }
36
37 public int getArgumentCount() {
38 return argumentCount;
39 }
40
41 public boolean isMethodOrConstructorInvocation() {
42 return isMethodOrConstructorInvocation;
43 }
44
45 public void setNameWhichThisQualifies(PLSQLNameOccurrence qualifiedName) {
46 this.qualifiedName = qualifiedName;
47 }
48
49 public PLSQLNameOccurrence getNameForWhichThisIsAQualifier() {
50 return qualifiedName;
51 }
52
53 public boolean isPartOfQualifiedName() {
54 return qualifiedName != null;
55 }
56
57 public PLSQLNode getLocation() {
58 return location;
59 }
60
61 public boolean isOnRightHandSide() {
62 Node node = location.jjtGetParent().jjtGetParent().jjtGetParent();
63 return node instanceof ASTExpression && node.jjtGetNumChildren() == 3;
64 }
65
66 public boolean isOnLeftHandSide() {
67 // I detest this method with every atom of my being
68 Node primaryExpression;
69 if (location.jjtGetParent() instanceof ASTPrimaryExpression) {
70 primaryExpression = location.jjtGetParent().jjtGetParent();
71 } else if (location.jjtGetParent().jjtGetParent() instanceof ASTPrimaryExpression) {
72 primaryExpression = location.jjtGetParent().jjtGetParent().jjtGetParent();
73 } else {
74 throw new RuntimeException(
75 "Found a NameOccurrence that didn't have an ASTPrimaryExpression as parent or grandparent. "
76 + " Node = " + location.getClass().getCanonicalName() + ", Parent = "
77 + location.jjtGetParent().getClass().getCanonicalName() + " and grandparent = "
78 + location.jjtGetParent().jjtGetParent().getClass().getCanonicalName() + " @ line = "
79 + location.getBeginLine() + ", column = " + location.getBeginColumn());
80 }
81
82 /*
83 * if (isStandAlonePostfix(primaryExpression)) { return true; }
84 */
85
86 if (primaryExpression.jjtGetNumChildren() <= 1) {
87 return false;
88 }
89
90 /*
91 * if (!(primaryExpression.jjtGetChild(1) instanceof
92 * ASTAssignmentOperator)) { return false; }
93 */
94
95 if (isPartOfQualifiedName() /* or is an array type */) {
96 return false;
97 }
98
99 /*
100 * if (isCompoundAssignment(primaryExpression)) { return false; }
101 */
102
103 return true;
104 }
105
106 /*
107 * private boolean isCompoundAssignment(Node primaryExpression) { return
108 * ((ASTAssignmentOperator) primaryExpression.jjtGetChild(1)).isCompound();
109 * }
110 *
111 * private boolean isStandAlonePostfix(Node primaryExpression) { if
112 * (!(primaryExpression instanceof ASTPostfixExpression) ||
113 * !(primaryExpression.jjtGetParent() instanceof ASTStatementExpression)) {
114 * return false; }
115 *
116 * ASTPrimaryPrefix pf = (ASTPrimaryPrefix) ((ASTPrimaryExpression)
117 * primaryExpression.jjtGetChild(0)).jjtGetChild(0); if
118 * (pf.usesThisModifier()) { return true; }
119 *
120 * return thirdChildHasDottedName(primaryExpression); }
121 *
122 * private boolean thirdChildHasDottedName(Node primaryExpression) { Node
123 * thirdChild =
124 * primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0); return
125 * thirdChild instanceof ASTName && ((ASTName)
126 * thirdChild).getImage().indexOf('.') == -1; }
127 */
128
129 /**
130 * Assert it the occurrence is a self assignment such as: <code>
131 * i += 3;
132 * </code>
133 *
134 * @return true, if the occurrence is self-assignment, false, otherwise.
135 */
136 /*
137 * @SuppressWarnings("PMD.AvoidBranchingStatementAsLastInLoop") public
138 * boolean isSelfAssignment() { Node l = location; while (true) { Node p =
139 * l.jjtGetParent(); Node gp = p.jjtGetParent(); Node node =
140 * gp.jjtGetParent(); if (node instanceof ASTPreDecrementExpression || node
141 * instanceof ASTPreIncrementExpression || node instanceof
142 * ASTPostfixExpression) { return true; }
143 *
144 * if (hasAssignmentOperator(gp)) { return isCompoundAssignment(gp); }
145 *
146 * if (hasAssignmentOperator(node)) { return isCompoundAssignment(node); }
147 *
148 * // deal with extra parenthesis: "(i)++" if (p instanceof ASTPrimaryPrefix
149 * && p.jjtGetNumChildren() == 1 && gp instanceof ASTPrimaryExpression &&
150 * gp.jjtGetNumChildren() == 1&& node instanceof ASTExpression &&
151 * node.jjtGetNumChildren() == 1 && node.jjtGetParent() instanceof
152 * ASTPrimaryPrefix && node.jjtGetParent().jjtGetNumChildren() == 1) { l =
153 * node; continue; }
154 *
155 * // catch this.i++ or ++this.i return gp instanceof
156 * ASTPreDecrementExpression || gp instanceof ASTPreIncrementExpression ||
157 * gp instanceof ASTPostfixExpression; } }
158 */
159
160 /*
161 * private boolean hasAssignmentOperator(Node node) { if (node instanceof
162 * ASTStatementExpression || node instanceof ASTExpression) { if
163 * (node.jjtGetNumChildren() >= 2 && node.jjtGetChild(1) instanceof
164 * ASTAssignmentOperator) { return true; } } return false; }
165 */
166
167 /**
168 * Simply return true is the image is equal to keyword 'this' or 'super'.
169 *
170 * @return return true if image equal to 'this' or 'super'.
171 */
172 public boolean isThisOrSuper() {
173 return image.equals(THIS) || image.equals(SUPER);
174 }
175
176 /**
177 * Simply return if the image start with keyword 'this' or 'super'.
178 *
179 * @return true, if keyword is used, false otherwise.
180 */
181 /*
182 * public boolean useThisOrSuper() { Node node = location.jjtGetParent(); if
183 * ( node instanceof ASTPrimaryExpression ) { ASTPrimaryExpression
184 * primaryExpression = (ASTPrimaryExpression)node; ASTPrimaryPrefix prefix =
185 * (ASTPrimaryPrefix) primaryExpression.jjtGetChild(0); if ( prefix != null
186 * ) { return prefix.usesSuperModifier() || prefix.usesThisModifier(); } }
187 * return image.startsWith(THIS_DOT) || image.startsWith(SUPER_DOT); }
188 */
189
190 @Override
191 public boolean equals(Object o) {
192 if (o instanceof PLSQLNameOccurrence) {
193 PLSQLNameOccurrence n = (PLSQLNameOccurrence) o;
194 return n.getImage().equals(getImage());
195 }
196 return false;
197 }
198
199 @Override
200 public int hashCode() {
201 return getImage().hashCode();
202 }
203
204 public String getImage() {
205 return image;
206 }
207
208 @Override
209 public String toString() {
210 return getImage() + ":" + location.getBeginLine() + ":" + location.getClass()
211 + (this.isMethodOrConstructorInvocation() ? "(method call)" : "");
212 }
213 }