Coverage Report - com.puppycrawl.tools.checkstyle.checks.DeclarationCollector
 
Classes in this File Line Coverage Branch Coverage Complexity
DeclarationCollector
100%
59/59
66%
32/48
3.222
DeclarationCollector$BlockFrame
100%
2/2
N/A
3.222
DeclarationCollector$ClassFrame
100%
10/10
100%
6/6
3.222
DeclarationCollector$GlobalFrame
100%
2/2
N/A
3.222
DeclarationCollector$LexicalFrame
100%
12/12
100%
4/4
3.222
DeclarationCollector$MethodFrame
100%
2/2
N/A
3.222
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 package com.puppycrawl.tools.checkstyle.checks;
 20  
 
 21  
 import com.google.common.collect.Lists;
 22  
 import com.google.common.collect.Maps;
 23  
 import com.google.common.collect.Sets;
 24  
 import com.puppycrawl.tools.checkstyle.api.Check;
 25  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 26  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 27  
 
 28  
 import java.util.Deque;
 29  
 import java.util.Map;
 30  
 import java.util.Queue;
 31  
 import java.util.Set;
 32  
 
 33  
 /**
 34  
  * Abstract class for checks which need to collect information about
 35  
  * declared members/parameters/variables.
 36  
  *
 37  
  * @author o_sukhodolsky
 38  
  */
 39  5
 public abstract class DeclarationCollector extends Check
 40  
 {
 41  
     /**
 42  
      * Tree of all the parsed frames
 43  
      */
 44  
     private Map<DetailAST, LexicalFrame> mFrames;
 45  
 
 46  
     /**
 47  
      * Frame for the currently processed AST
 48  
      */
 49  
     private LexicalFrame mCurrent;
 50  
 
 51  
     @Override
 52  
     public void beginTree(DetailAST aRootAST)
 53  
     {
 54  5
         final Deque<LexicalFrame> aFrameStack = Lists.newLinkedList();
 55  5
         aFrameStack.add(new GlobalFrame());
 56  
 
 57  5
         mFrames = Maps.newHashMap();
 58  
 
 59  5
         DetailAST curNode = aRootAST;
 60  1477
         while (curNode != null) {
 61  1472
             collectDeclarations(aFrameStack, curNode);
 62  1472
             DetailAST toVisit = curNode.getFirstChild();
 63  2944
             while (curNode != null && toVisit == null) {
 64  1472
                 endCollectingDeclarations(aFrameStack, curNode);
 65  1472
                 toVisit = curNode.getNextSibling();
 66  1472
                 if (toVisit == null) {
 67  540
                     curNode = curNode.getParent();
 68  
                 }
 69  
             }
 70  1472
             curNode = toVisit;
 71  1472
         }
 72  5
     }
 73  
 
 74  
     @Override
 75  
     public void visitToken(DetailAST aAST)
 76  
     {
 77  368
         switch (aAST.getType()) {
 78  
         case TokenTypes.CLASS_DEF :
 79  
         case TokenTypes.INTERFACE_DEF :
 80  
         case TokenTypes.ENUM_DEF :
 81  
         case TokenTypes.ANNOTATION_DEF :
 82  
         case TokenTypes.SLIST :
 83  
         case TokenTypes.METHOD_DEF :
 84  
         case TokenTypes.CTOR_DEF :
 85  94
             this.mCurrent = this.mFrames.get(aAST);
 86  94
             break;
 87  
         default :
 88  
             // do nothing
 89  
         }
 90  368
     } // end visitToken
 91  
 
 92  
     /**
 93  
      * Parse the next AST for declarations
 94  
      *
 95  
      * @param aFrameStack Stack containing the FrameTree being built
 96  
      * @param aAST AST to parse
 97  
      */
 98  
     private void collectDeclarations(Deque<LexicalFrame> aFrameStack,
 99  
         DetailAST aAST)
 100  
     {
 101  1472
         final LexicalFrame frame = aFrameStack.peek();
 102  1472
         switch (aAST.getType()) {
 103  
         case TokenTypes.VARIABLE_DEF :  {
 104  23
             final String name =
 105  
                     aAST.findFirstToken(TokenTypes.IDENT).getText();
 106  23
             if (frame instanceof ClassFrame) {
 107  22
                 final DetailAST mods =
 108  
                     aAST.findFirstToken(TokenTypes.MODIFIERS);
 109  22
                 if (mods.branchContains(TokenTypes.LITERAL_STATIC)) {
 110  3
                     ((ClassFrame) frame).addStaticMember(name);
 111  
                 }
 112  
                 else {
 113  19
                     ((ClassFrame) frame).addInstanceMember(name);
 114  
                 }
 115  22
             }
 116  
             else {
 117  1
                 frame.addName(name);
 118  
             }
 119  1
             break;
 120  
         }
 121  
         case TokenTypes.PARAMETER_DEF : {
 122  6
             final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT);
 123  6
             frame.addName(nameAST.getText());
 124  6
             break;
 125  
         }
 126  
         case TokenTypes.CLASS_DEF :
 127  
         case TokenTypes.INTERFACE_DEF :
 128  
         case TokenTypes.ENUM_DEF :
 129  
         case TokenTypes.ANNOTATION_DEF : {
 130  30
             final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT);
 131  30
             frame.addName(nameAST.getText());
 132  30
             aFrameStack.addFirst(new ClassFrame(frame));
 133  30
             break;
 134  
         }
 135  
         case TokenTypes.SLIST :
 136  37
             aFrameStack.addFirst(new BlockFrame(frame));
 137  37
             break;
 138  
         case TokenTypes.METHOD_DEF : {
 139  27
             final String name = aAST.findFirstToken(TokenTypes.IDENT).getText();
 140  27
             if (frame instanceof ClassFrame) {
 141  27
                 final DetailAST mods =
 142  
                     aAST.findFirstToken(TokenTypes.MODIFIERS);
 143  27
                 if (mods.branchContains(TokenTypes.LITERAL_STATIC)) {
 144  3
                     ((ClassFrame) frame).addStaticMember(name);
 145  
                 }
 146  
                 else {
 147  24
                     ((ClassFrame) frame).addInstanceMember(name);
 148  
                 }
 149  
             }
 150  
         }
 151  
         case TokenTypes.CTOR_DEF :
 152  31
             aFrameStack.addFirst(new MethodFrame(frame));
 153  31
             break;
 154  
         default:
 155  
             // do nothing
 156  
         }
 157  1472
     }
 158  
 
 159  
 
 160  
     /**
 161  
      * End parsing of the AST for declarations.
 162  
      *
 163  
      * @param aFrameStack Stack containing the FrameTree being built
 164  
      * @param aAST AST that was parsed
 165  
      */
 166  
     private void endCollectingDeclarations(Queue<LexicalFrame> aFrameStack,
 167  
         DetailAST aAST)
 168  
     {
 169  1472
         switch (aAST.getType()) {
 170  
         case TokenTypes.CLASS_DEF :
 171  
         case TokenTypes.INTERFACE_DEF :
 172  
         case TokenTypes.ENUM_DEF :
 173  
         case TokenTypes.ANNOTATION_DEF :
 174  
         case TokenTypes.SLIST :
 175  
         case TokenTypes.METHOD_DEF :
 176  
         case TokenTypes.CTOR_DEF :
 177  98
             this.mFrames.put(aAST, aFrameStack.poll());
 178  98
             break;
 179  
         default :
 180  
             // do nothing
 181  
         }
 182  1472
     }
 183  
 
 184  
     /**
 185  
      * Check if given name is a name for class field in current environment.
 186  
      * @param aName a name to check
 187  
      * @return true is the given name is name of method or member.
 188  
      */
 189  
     protected final boolean isClassField(String aName)
 190  
     {
 191  47
         final LexicalFrame frame = findFrame(aName);
 192  47
         return (frame instanceof ClassFrame)
 193  
                 && ((ClassFrame) frame).hasInstanceMember(aName);
 194  
     }
 195  
 
 196  
     /**
 197  
      * Find frame containing declaration
 198  
      * @param aName name of the declaration to find
 199  
      * @return LexicalFrame containing declaration or null
 200  
      */
 201  
     private LexicalFrame findFrame(String aName)
 202  
     {
 203  47
         if (mCurrent != null) {
 204  46
             return mCurrent.getIfContains(aName);
 205  
         }
 206  
         else {
 207  1
             return null;
 208  
         }
 209  
     }
 210  
 
 211  
     /**
 212  
      * A declaration frame.
 213  
      * @author Stephen Bloch
 214  
      * June 19, 2003
 215  
      */
 216  
     private abstract static class LexicalFrame
 217  
     {
 218  
         /** Set of name of variables declared in this frame. */
 219  
         private final Set<String> mVarNames;
 220  
         /**
 221  
          * Parent frame.
 222  
          */
 223  
         private final LexicalFrame mParent;
 224  
 
 225  
         /**
 226  
          * constructor -- invokable only via super() from subclasses
 227  
          *
 228  
          * @param aParent parent frame
 229  
          */
 230  
         protected LexicalFrame(LexicalFrame aParent)
 231  103
         {
 232  103
             mParent = aParent;
 233  103
             mVarNames = Sets.newHashSet();
 234  103
         }
 235  
 
 236  
         /** add a name to the frame.
 237  
          * @param aNameToAdd  the name we're adding
 238  
          */
 239  
         void addName(String aNameToAdd)
 240  
         {
 241  37
             mVarNames.add(aNameToAdd);
 242  37
         }
 243  
 
 244  
         /** check whether the frame contains a given name.
 245  
          * @param aNameToFind  the name we're looking for
 246  
          * @return whether it was found
 247  
          */
 248  
         boolean contains(String aNameToFind)
 249  
         {
 250  123
             return mVarNames.contains(aNameToFind);
 251  
         }
 252  
 
 253  
         /** check whether the frame contains a given name.
 254  
          * @param aNameToFind  the name we're looking for
 255  
          * @return whether it was found
 256  
          */
 257  
         LexicalFrame getIfContains(String aNameToFind)
 258  
         {
 259  123
             if (contains(aNameToFind)) {
 260  26
                 return this;
 261  
             }
 262  97
             else if (mParent != null) {
 263  77
                 return mParent.getIfContains(aNameToFind);
 264  
             }
 265  
             else {
 266  20
                 return null;
 267  
             }
 268  
         }
 269  
     }
 270  
 
 271  
     /**
 272  
      * The global frame; should hold only class names.
 273  
      * @author Stephen Bloch
 274  
      */
 275  
     private static class GlobalFrame extends LexicalFrame
 276  
     {
 277  
 
 278  
         /**
 279  
          * Constructor for the root of the FrameTree
 280  
          */
 281  
         protected GlobalFrame()
 282  
         {
 283  5
             super(null);
 284  5
         }
 285  
     }
 286  
 
 287  
     /**
 288  
      * A frame initiated at method definition; holds parameter names.
 289  
      * @author Stephen Bloch
 290  
      */
 291  
     private static class MethodFrame extends LexicalFrame
 292  
     {
 293  
         /**
 294  
          * @param aParent parent frame
 295  
          */
 296  
         protected MethodFrame(LexicalFrame aParent)
 297  
         {
 298  31
             super(aParent);
 299  31
         }
 300  
     }
 301  
 
 302  
     /**
 303  
      * A frame initiated at class definition; holds instance variable
 304  
      * names.  For the present, I'm not worried about other class names,
 305  
      * method names, etc.
 306  
      * @author Stephen Bloch
 307  
      */
 308  
     private static class ClassFrame extends LexicalFrame
 309  
     {
 310  
         /** Set of name of instance members declared in this frame. */
 311  
         private final Set<String> mInstanceMembers;
 312  
         /** Set of name of variables declared in this frame. */
 313  
         private final Set<String> mStaticMembers;
 314  
 
 315  
         /**
 316  
          * Creates new instance of ClassFrame
 317  
          * @param aParent parent frame
 318  
          */
 319  
         public ClassFrame(LexicalFrame aParent)
 320  
         {
 321  30
             super(aParent);
 322  30
             mInstanceMembers = Sets.newHashSet();
 323  30
             mStaticMembers = Sets.newHashSet();
 324  30
         }
 325  
 
 326  
         /**
 327  
          * Adds static member's name.
 328  
          * @param aName a name of static member of the class
 329  
          */
 330  
         public void addStaticMember(final String aName)
 331  
         {
 332  6
             mStaticMembers.add(aName);
 333  6
         }
 334  
 
 335  
         /**
 336  
          * Adds instance member's name.
 337  
          * @param aName a name of instance member of the class
 338  
          */
 339  
         public void addInstanceMember(final String aName)
 340  
         {
 341  43
             mInstanceMembers.add(aName);
 342  43
         }
 343  
 
 344  
         /**
 345  
          * Checks if a given name is a known instance member of the class.
 346  
          * @param aName a name to check
 347  
          * @return true is the given name is a name of a known
 348  
          *         instance member of the class
 349  
          */
 350  
         public boolean hasInstanceMember(final String aName)
 351  
         {
 352  18
             return mInstanceMembers.contains(aName);
 353  
         }
 354  
 
 355  
         @Override
 356  
         boolean contains(String aNameToFind)
 357  
         {
 358  49
             return super.contains(aNameToFind)
 359  
                     || mInstanceMembers.contains(aNameToFind)
 360  
                     || mStaticMembers.contains(aNameToFind);
 361  
         }
 362  
     }
 363  
 
 364  
     /**
 365  
      * A frame initiated on entering a statement list; holds local variable
 366  
      * names.  For the present, I'm not worried about other class names,
 367  
      * method names, etc.
 368  
      * @author Stephen Bloch
 369  
      */
 370  5
     private static class BlockFrame extends LexicalFrame
 371  
     {
 372  
 
 373  
         /**
 374  
          * @param aParent parent frame
 375  
          */
 376  
         protected BlockFrame(LexicalFrame aParent)
 377  
         {
 378  37
             super(aParent);
 379  37
         }
 380  
     }
 381  
 }