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 }