View Javadoc

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          // I detest this method with every atom of my being
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() /* or is an array type */) {
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 }