Coverage Report - com.puppycrawl.tools.checkstyle.api.ScopeUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ScopeUtils
93%
93/99
89%
89/100
5.9
 
 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.api;
 20  
 
 21  
 import antlr.collections.AST;
 22  
 
 23  
 /**
 24  
  * Contains utility methods for working on scope.
 25  
  *
 26  
  * @author Oliver Burn
 27  
  * @version 1.0
 28  
  */
 29  
 public final class ScopeUtils
 30  
 {
 31  
     ///CLOVER:OFF
 32  
     /** prevent instantiation */
 33  
     private ScopeUtils()
 34  0
     {
 35  0
     }
 36  
     ///CLOVER:ON
 37  
 
 38  
     /**
 39  
      * Returns the Scope specified by the modifier set.
 40  
      *
 41  
      * @param aMods root node of a modifier set
 42  
      * @return a <code>Scope</code> value
 43  
      */
 44  
     public static Scope getScopeFromMods(DetailAST aMods)
 45  
     {
 46  2695
         Scope retVal = Scope.PACKAGE; // default scope
 47  2695
         for (AST token = aMods.getFirstChild();
 48  2754
             token != null;
 49  59
             token = token.getNextSibling())
 50  
         {
 51  1932
             if ("public".equals(token.getText())) {
 52  1307
                 retVal = Scope.PUBLIC;
 53  1307
                 break;
 54  
             }
 55  625
             else if ("protected".equals(token.getText())) {
 56  199
                 retVal = Scope.PROTECTED;
 57  199
                 break;
 58  
             }
 59  426
             else if ("private".equals(token.getText())) {
 60  367
                 retVal = Scope.PRIVATE;
 61  367
                 break;
 62  
             }
 63  
         }
 64  2695
         return retVal;
 65  
     }
 66  
 
 67  
     /**
 68  
      * Returns the scope of the surrounding "block".
 69  
      * @param aAST the node to return the scope for
 70  
      * @return the Scope of the surrounding block
 71  
      */
 72  
     public static Scope getSurroundingScope(DetailAST aAST)
 73  
     {
 74  1188
         Scope retVal = null;
 75  1188
         for (DetailAST token = aAST.getParent();
 76  4509
              token != null;
 77  3321
              token = token.getParent())
 78  
         {
 79  3336
             final int type = token.getType();
 80  3336
             if ((type == TokenTypes.CLASS_DEF)
 81  
                 || (type == TokenTypes.INTERFACE_DEF)
 82  
                 || (type == TokenTypes.ANNOTATION_DEF)
 83  
                 || (type == TokenTypes.ENUM_DEF))
 84  
             {
 85  1461
                 final DetailAST mods =
 86  
                     token.findFirstToken(TokenTypes.MODIFIERS);
 87  1461
                 final Scope modScope = ScopeUtils.getScopeFromMods(mods);
 88  1461
                 if ((retVal == null) || (retVal.isIn(modScope))) {
 89  1282
                     retVal = modScope;
 90  
                 }
 91  1461
             }
 92  1875
             else if (type == TokenTypes.LITERAL_NEW) {
 93  15
                 retVal = Scope.ANONINNER;
 94  15
                 break; //because Scope.ANONINNER is not in any other Scope
 95  
             }
 96  
         }
 97  
 
 98  1188
         return retVal;
 99  
     }
 100  
 
 101  
     /**
 102  
      * Returns whether a node is directly contained within an interface block.
 103  
      *
 104  
      * @param aAST the node to check if directly contained within an interface
 105  
      * block
 106  
      * @return a <code>boolean</code> value
 107  
      */
 108  
     public static boolean inInterfaceBlock(DetailAST aAST)
 109  
     {
 110  2550
         boolean retVal = false;
 111  
 
 112  
         // Loop up looking for a containing interface block
 113  2550
         for (DetailAST token = aAST.getParent();
 114  6197
              token != null;
 115  3647
              token = token.getParent())
 116  
         {
 117  6112
             final int type = token.getType();
 118  6112
             if ((type == TokenTypes.CLASS_DEF)
 119  
                 || (type == TokenTypes.ENUM_DEF)
 120  
                 || (type == TokenTypes.ANNOTATION_DEF))
 121  
             {
 122  23
                 break; // in a class, enum or annotation
 123  
             }
 124  3730
             else if (type == TokenTypes.LITERAL_NEW) {
 125  22
                 break; // inner implementation
 126  
             }
 127  3708
             else if (type == TokenTypes.INTERFACE_DEF) {
 128  61
                 retVal = true;
 129  61
                 break;
 130  
             }
 131  
         }
 132  
 
 133  2550
         return retVal;
 134  
     }
 135  
 
 136  
     /**
 137  
      * Returns whether a node is directly contained within an annotation block.
 138  
      *
 139  
      * @param aAST the node to check if directly contained within an annotation
 140  
      * block
 141  
      * @return a <code>boolean</code> value
 142  
      */
 143  
     public static boolean inAnnotationBlock(DetailAST aAST)
 144  
     {
 145  2483
         boolean retVal = false;
 146  
 
 147  
         // Loop up looking for a containing interface block
 148  2483
         for (DetailAST token = aAST.getParent();
 149  6037
              token != null;
 150  3554
              token = token.getParent())
 151  
         {
 152  5952
             final int type = token.getType();
 153  5952
             if ((type == TokenTypes.CLASS_DEF)
 154  
                 || (type == TokenTypes.ENUM_DEF)
 155  
                 || (type == TokenTypes.INTERFACE_DEF))
 156  
             {
 157  0
                 break; // in a class, enum or interface
 158  
             }
 159  3599
             else if (type == TokenTypes.LITERAL_NEW) {
 160  22
                 break; // inner implementation
 161  
             }
 162  3577
             else if (type == TokenTypes.ANNOTATION_DEF) {
 163  23
                 retVal = true;
 164  23
                 break;
 165  
             }
 166  
         }
 167  
 
 168  2483
         return retVal;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Returns whether a node is directly contained within an interface or
 173  
      * annotation block.
 174  
      *
 175  
      * @param aAST the node to check if directly contained within an interface
 176  
      * or annotation block
 177  
      * @return a <code>boolean</code> value
 178  
      */
 179  
     public static boolean inInterfaceOrAnnotationBlock(DetailAST aAST)
 180  
     {
 181  2543
         return inInterfaceBlock(aAST) || inAnnotationBlock(aAST);
 182  
     }
 183  
 
 184  
     /**
 185  
      * Returns whether a node is directly contained within an enum block.
 186  
      *
 187  
      * @param aAST the node to check if directly contained within an enum
 188  
      * block
 189  
      * @return a <code>boolean</code> value
 190  
      */
 191  
     public static boolean inEnumBlock(DetailAST aAST)
 192  
     {
 193  9
         boolean retVal = false;
 194  
 
 195  
         // Loop up looking for a containing interface block
 196  9
         for (DetailAST token = aAST.getParent();
 197  18
              token != null;
 198  9
              token = token.getParent())
 199  
         {
 200  18
             final int type = token.getType();
 201  18
             if ((type == TokenTypes.INTERFACE_DEF)
 202  
                 || (type == TokenTypes.ANNOTATION_DEF)
 203  
                 || (type == TokenTypes.CLASS_DEF))
 204  
             {
 205  8
                 break; // in an interface, annotation or class
 206  
             }
 207  10
             else if (type == TokenTypes.LITERAL_NEW) {
 208  0
                 break; // inner implementation, enums can't be inner classes
 209  
             }
 210  10
             else if (type == TokenTypes.ENUM_DEF) {
 211  1
                 retVal = true;
 212  1
                 break;
 213  
             }
 214  
         }
 215  
 
 216  9
         return retVal;
 217  
     }
 218  
 
 219  
     /**
 220  
      * Returns whether the scope of a node is restricted to a code block.
 221  
      * A code block is a method or constructor body, or a initialiser block.
 222  
      *
 223  
      * @param aAST the node to check
 224  
      * @return a <code>boolean</code> value
 225  
      */
 226  
     public static boolean inCodeBlock(DetailAST aAST)
 227  
     {
 228  568
         boolean retVal = false;
 229  
 
 230  
         // Loop up looking for a containing code block
 231  568
         for (DetailAST token = aAST.getParent();
 232  2239
              token != null;
 233  1671
              token = token.getParent())
 234  
         {
 235  1718
             final int type = token.getType();
 236  1718
             if ((type == TokenTypes.METHOD_DEF)
 237  
                 || (type == TokenTypes.CTOR_DEF)
 238  
                 || (type == TokenTypes.INSTANCE_INIT)
 239  
                 || (type == TokenTypes.STATIC_INIT))
 240  
             {
 241  47
                 retVal = true;
 242  47
                 break;
 243  
             }
 244  
         }
 245  
 
 246  568
         return retVal;
 247  
     }
 248  
 
 249  
     /**
 250  
      * Returns whether a node is contained in the outer most type block.
 251  
      *
 252  
      * @param aAST the node to check
 253  
      * @return a <code>boolean</code> value
 254  
      */
 255  
     public static boolean isOuterMostType(DetailAST aAST)
 256  
     {
 257  68
         boolean retVal = true;
 258  68
         for (DetailAST parent = aAST.getParent();
 259  73
              parent != null;
 260  5
              parent = parent.getParent())
 261  
         {
 262  10
             if ((parent.getType() == TokenTypes.CLASS_DEF)
 263  
                 || (parent.getType() == TokenTypes.INTERFACE_DEF)
 264  
                 || (parent.getType() == TokenTypes.ANNOTATION_DEF)
 265  
                 || (parent.getType() == TokenTypes.ENUM_DEF))
 266  
             {
 267  5
                 retVal = false;
 268  5
                 break;
 269  
             }
 270  
         }
 271  
 
 272  68
         return retVal;
 273  
     }
 274  
 
 275  
     /**
 276  
      * Determines whether a node is a local variable definition.
 277  
      * I.e. if it is declared in a code block, a for initializer,
 278  
      * or a catch parameter.
 279  
      * @param aAST the node to check.
 280  
      * @return whether aAST is a local variable definition.
 281  
      */
 282  
     public static boolean isLocalVariableDef(DetailAST aAST)
 283  
     {
 284  
         // variable declaration?
 285  1199
         if (aAST.getType() == TokenTypes.VARIABLE_DEF) {
 286  1103
             final DetailAST parent = aAST.getParent();
 287  1103
             if (parent != null) {
 288  1103
                 final int type = parent.getType();
 289  1103
                 return (type == TokenTypes.SLIST)
 290  
                     || (type == TokenTypes.FOR_INIT)
 291  
                     || (type == TokenTypes.FOR_EACH_CLAUSE);
 292  
             }
 293  0
         }
 294  
         // catch parameter?
 295  96
         else if (aAST.getType() == TokenTypes.PARAMETER_DEF) {
 296  96
             final DetailAST parent = aAST.getParent();
 297  96
             if (parent != null) {
 298  96
                 return (parent.getType() == TokenTypes.LITERAL_CATCH);
 299  
             }
 300  
         }
 301  0
         return false;
 302  
     }
 303  
 }