net.sourceforge.pmd.rules
Class ConstructorCallsOverridableMethodRule

java.lang.Object
  extended bynet.sourceforge.pmd.ast.JavaParserVisitorAdapter
      extended bynet.sourceforge.pmd.AbstractRule
          extended bynet.sourceforge.pmd.rules.ConstructorCallsOverridableMethodRule
All Implemented Interfaces:
JavaParserVisitor, Rule

public final class ConstructorCallsOverridableMethodRule
extends AbstractRule

Searches through all methods and constructors called from constructors. It marks as dangerous any call to overridable methods from non-private constructors. It marks as dangerous any calls to dangerous private constructors from non-private constructors.

Author:
CL Gilbert (dnoyeb@users.sourceforge.net)

Nested Class Summary
private  class ConstructorCallsOverridableMethodRule.ConstructorHolder
           
private  class ConstructorCallsOverridableMethodRule.ConstructorInvocation
           
private static class ConstructorCallsOverridableMethodRule.EvalPackage
          1 package per class.
private  class ConstructorCallsOverridableMethodRule.MethodHolder
           
private static class ConstructorCallsOverridableMethodRule.MethodInvocation
          2: method(); ASTPrimaryPrefix ASTName image = "method" ASTPrimarySuffix *ASTArguments 3: a.method(); ASTPrimaryPrefix -> ASTName image = "a.method" ??? ASTPrimarySuffix -> () ASTArguments 3: this.method(); ASTPrimaryPrefix -> this image=null ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments super.method(); ASTPrimaryPrefix -> image = "method" ASTPrimarySuffix -> image = null ASTArguments -> super.a.method(); ASTPrimaryPrefix -> image = "a" ASTPrimarySuffix -> image = "method" ASTPrimarySuffix -> image = null ASTArguments -> 4: this.a.method(); ASTPrimaryPrefix -> image = null ASTPrimarySuffix -> image = "a" ASTPrimarySuffix -> image = "method" ASTPrimarySuffix -> ASTArguments 4: ClassName.this.method(); ASTPrimaryPrefix ASTName image = "ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image = "method" ASTPrimarySuffix -> () ASTArguments 5: ClassName.this.a.method(); ASTPrimaryPrefix ASTName image = "ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image="a" ASTPrimarySuffix -> image="method" ASTPrimarySuffix -> () ASTArguments 5: Package.ClassName.this.method(); ASTPrimaryPrefix ASTName image ="Package.ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> image="method" ASTPrimarySuffix -> () ASTArguments 6: Package.ClassName.this.a.method(); ASTPrimaryPrefix ASTName image ="Package.ClassName" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> a ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments 5: OuterClass.InnerClass.this.method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments 6: OuterClass.InnerClass.this.a.method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> a ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments OuterClass.InnerClass.this.a.method().method().method(); ASTPrimaryPrefix ASTName image = "OuterClass.InnerClass" ASTPrimarySuffix -> this image=null ASTPrimarySuffix -> a image='a' ASTPrimarySuffix -> method image='method' ASTPrimarySuffix -> () image=null ASTArguments ASTPrimarySuffix -> method image='method' ASTPrimarySuffix -> () image=null ASTArguments ASTPrimarySuffix -> method image='method' ASTPrimarySuffix -> () image=null ASTArguments 3..n: Class.InnerClass[0].InnerClass[n].this.method(); ASTPrimaryPrefix ASTName image = "Class[0]..InnerClass[n]" ASTPrimarySuffix -> image=null ASTPrimarySuffix -> method ASTPrimarySuffix -> () ASTArguments super.aMethod(); ASTPrimaryPrefix -> aMethod ASTPrimarySuffix -> () Evaluate right to left
private static class ConstructorCallsOverridableMethodRule.NullEvalPackage
           
 
Field Summary
private  java.util.List evalPackages
          1 package per class.
private static ConstructorCallsOverridableMethodRule.NullEvalPackage nullEvalPackage
           
 
Fields inherited from class net.sourceforge.pmd.AbstractRule
 
Fields inherited from interface net.sourceforge.pmd.Rule
LOWEST_PRIORITY, PRIORITIES
 
Constructor Summary
ConstructorCallsOverridableMethodRule()
           
 
Method Summary
private static void addCalledMethodsOfNode(AccessNode node, java.util.List calledMethods, java.lang.String className)
           
private static void addCalledMethodsOfNode(SimpleNode node, java.util.List calledMethods, java.lang.String className)
          Adds all methods called on this instance from within this Node.
private static void addCalledMethodsOfNodeImpl(java.util.List expressions, java.util.List calledMethods, java.lang.String className)
           
private  void clearEvalPackages()
           
private  void evaluateDangerOfConstructors1(java.util.Map classConstructorMap, java.util.Set evaluatedMethods)
          marks constructors dangerous if they call any dangerous methods Requires only a single pass as methods are already marked
private  boolean evaluateDangerOfConstructors2(java.util.Map classConstructorMap)
          Constructor map should contain a key for each private constructor, and maps to a List which contains all called constructors of that key.
private  boolean evaluateDangerOfMethods(java.util.Map classMethodMap)
          Check the methods called on this class by each of the methods on this class.
private static ConstructorCallsOverridableMethodRule.MethodInvocation findMethod(ASTPrimaryExpression node, java.lang.String className)
           
private  ConstructorCallsOverridableMethodRule.EvalPackage getCurrentEvalPackage()
           
private static java.lang.String getNameFromPrefix(ASTPrimaryPrefix node)
          ASTPrimaryPrefix has name in child node of ASTName
private static java.lang.String getNameFromSuffix(ASTPrimarySuffix node)
          ASTPrimarySuffix has name in itself
private  void putEvalPackage(ConstructorCallsOverridableMethodRule.EvalPackage ep)
          Adds and evaluation package and makes it current
private  void removeCurrentEvalPackage()
           
 java.lang.Object visit(ASTClassDeclaration node, java.lang.Object data)
          This check must be evaluated independelty for each class.
 java.lang.Object visit(ASTCompilationUnit node, java.lang.Object data)
          Work on each file independently.
 java.lang.Object visit(ASTConstructorDeclaration node, java.lang.Object data)
          Non-private constructor's methods are added to a list for later safety evaluation.
 java.lang.Object visit(ASTInterfaceDeclaration node, java.lang.Object data)
           
 java.lang.Object visit(ASTMethodDeclarator node, java.lang.Object data)
          Create a MethodHolder to hold the method.
 java.lang.Object visit(ASTNestedClassDeclaration node, java.lang.Object data)
           
 java.lang.Object visit(ASTNestedInterfaceDeclaration node, java.lang.Object data)
           
private  java.lang.Object visitClassDec(AccessNode node, java.lang.Object data)
          This check must be evaluated independelty for each class.
 
Methods inherited from class net.sourceforge.pmd.AbstractRule
addProperty, apply, createRuleViolation, createRuleViolation, equals, getBooleanProperty, getDescription, getDoubleProperty, getExample, getIntProperty, getMessage, getName, getPriority, getPriorityName, getProperties, getStringProperty, hashCode, hasProperty, include, setDescription, setExample, setInclude, setMessage, setName, setPriority, visitAll
 
Methods inherited from class net.sourceforge.pmd.ast.JavaParserVisitorAdapter
visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

nullEvalPackage

private static final ConstructorCallsOverridableMethodRule.NullEvalPackage nullEvalPackage

evalPackages

private final java.util.List evalPackages
1 package per class.

Constructor Detail

ConstructorCallsOverridableMethodRule

public ConstructorCallsOverridableMethodRule()
Method Detail

getCurrentEvalPackage

private ConstructorCallsOverridableMethodRule.EvalPackage getCurrentEvalPackage()

putEvalPackage

private void putEvalPackage(ConstructorCallsOverridableMethodRule.EvalPackage ep)
Adds and evaluation package and makes it current


removeCurrentEvalPackage

private void removeCurrentEvalPackage()

clearEvalPackages

private void clearEvalPackages()

visitClassDec

private java.lang.Object visitClassDec(AccessNode node,
                                       java.lang.Object data)
This check must be evaluated independelty for each class. Inner classses get their own EvalPackage in order to perform independent evaluation.


evaluateDangerOfMethods

private boolean evaluateDangerOfMethods(java.util.Map classMethodMap)
Check the methods called on this class by each of the methods on this class. If a method calls an unsafe method, mark the calling method as unsafe. This changes the list of unsafe methods which necessitates another pass. Keep passing until you make a clean pass in which no methods are changed to unsafe. For speed it is possible to limit the number of passes. Impossible to tell type of arguments to method, so forget method matching on types. just use name and num of arguments. will be some false hits, but oh well.


evaluateDangerOfConstructors1

private void evaluateDangerOfConstructors1(java.util.Map classConstructorMap,
                                           java.util.Set evaluatedMethods)
marks constructors dangerous if they call any dangerous methods Requires only a single pass as methods are already marked


evaluateDangerOfConstructors2

private boolean evaluateDangerOfConstructors2(java.util.Map classConstructorMap)
Constructor map should contain a key for each private constructor, and maps to a List which contains all called constructors of that key. marks dangerous if call dangerous private constructor we ignore all non-private constructors here. That is, the map passed in should not contain any non-private constructors. we return boolean in order to limit the number of passes through this method but it seems as if we can forgo that and just process it till its done.


visit

public java.lang.Object visit(ASTCompilationUnit node,
                              java.lang.Object data)
Work on each file independently.

Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTClassDeclaration node,
                              java.lang.Object data)
This check must be evaluated independelty for each class. Inner classses get their own EvalPackage in order to perform independent evaluation.

Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTNestedClassDeclaration node,
                              java.lang.Object data)
Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTInterfaceDeclaration node,
                              java.lang.Object data)
Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTNestedInterfaceDeclaration node,
                              java.lang.Object data)
Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTConstructorDeclaration node,
                              java.lang.Object data)
Non-private constructor's methods are added to a list for later safety evaluation. Non-private constructor's calls on private constructors are added to a list for later safety evaluation. Private constructors are added to a list so their safety to be called can be later evaluated. Note: We are not checking private constructor's calls on non-private constructors because all non-private constructors will be evaluated for safety anyway. This means we wont flag a private constructor as unsafe just because it calls an unsafe public constructor. We want to show only 1 instance of an error, and this would be 2 instances of the same error.

Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

visit

public java.lang.Object visit(ASTMethodDeclarator node,
                              java.lang.Object data)
Create a MethodHolder to hold the method. Store the MethodHolder in the Map as the key Store each method called by the current method as a List in the Map as the Object

Specified by:
visit in interface JavaParserVisitor
Overrides:
visit in class JavaParserVisitorAdapter

addCalledMethodsOfNode

private static void addCalledMethodsOfNode(AccessNode node,
                                           java.util.List calledMethods,
                                           java.lang.String className)

addCalledMethodsOfNode

private static void addCalledMethodsOfNode(SimpleNode node,
                                           java.util.List calledMethods,
                                           java.lang.String className)
Adds all methods called on this instance from within this Node.


addCalledMethodsOfNodeImpl

private static void addCalledMethodsOfNodeImpl(java.util.List expressions,
                                               java.util.List calledMethods,
                                               java.lang.String className)

findMethod

private static ConstructorCallsOverridableMethodRule.MethodInvocation findMethod(ASTPrimaryExpression node,
                                                                                 java.lang.String className)
Returns:
A method call on the class passed in, or null if no method call is found.

getNameFromPrefix

private static java.lang.String getNameFromPrefix(ASTPrimaryPrefix node)
ASTPrimaryPrefix has name in child node of ASTName


getNameFromSuffix

private static java.lang.String getNameFromSuffix(ASTPrimarySuffix node)
ASTPrimarySuffix has name in itself