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.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 }