View Javadoc

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