Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.DeclarationOrderCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
DeclarationOrderCheck
92%
50/54
82%
33/40
5
DeclarationOrderCheck$1
N/A
N/A
5
DeclarationOrderCheck$ScopeState
100%
3/3
N/A
5
 
 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.coding;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.Check;
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.FastStack;
 24  
 import com.puppycrawl.tools.checkstyle.api.Scope;
 25  
 import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
 26  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 27  
 
 28  
 /**
 29  
  * <p>
 30  
  * Checks that the parts of a class or interface declaration
 31  
  * appear in the order suggested by the
 32  
  * <a
 33  
  * href="http://java.sun.com/docs/codeconv/html/CodeConventions.doc2.html#1852"
 34  
  * >Code Conventions for the Java Programming Language</a>.
 35  
  * </p>
 36  
  * <p>
 37  
  * <ol>
 38  
  * <li> Class (static) variables. First the public class variables, then
 39  
  *      the protected, then package level (no access modifier), and then
 40  
  *      the private. </li>
 41  
  * <li> Instance variables. First the public class variables, then
 42  
  *      the protected, then package level (no access modifier), and then
 43  
  *      the private. </li>
 44  
  * <li> Constructors </li>
 45  
  * <li> Methods </li>
 46  
  * </ol>
 47  
  * </p>
 48  
  * <p>
 49  
  * An example of how to configure the check is:
 50  
  * </p>
 51  
  * <pre>
 52  
  * &lt;module name="DeclarationOrder"/&gt;
 53  
  * </pre>
 54  
  *
 55  
  * @author r_auckenthaler
 56  
  */
 57  3
 public class DeclarationOrderCheck extends Check
 58  
 {
 59  
     /** State for the VARIABLE_DEF */
 60  
     private static final int STATE_STATIC_VARIABLE_DEF = 1;
 61  
 
 62  
     /** State for the VARIABLE_DEF */
 63  
     private static final int STATE_INSTANCE_VARIABLE_DEF = 2;
 64  
 
 65  
     /** State for the CTOR_DEF */
 66  
     private static final int STATE_CTOR_DEF = 3;
 67  
 
 68  
     /** State for the METHOD_DEF */
 69  
     private static final int STATE_METHOD_DEF = 4;
 70  
 
 71  
     /**
 72  
      * List of Declaration States. This is necessary due to
 73  
      * inner classes that have their own state
 74  
      */
 75  3
     private final FastStack<ScopeState> mScopeStates = FastStack.newInstance();
 76  
 
 77  
     /**
 78  
      * private class to encapsulate the state
 79  
      */
 80  398
     private static class ScopeState
 81  
     {
 82  
         /** The state the check is in */
 83  15
         private int mScopeState = STATE_STATIC_VARIABLE_DEF;
 84  
 
 85  
         /** The sub-state the check is in */
 86  15
         private Scope mDeclarationAccess = Scope.PUBLIC;
 87  
     }
 88  
 
 89  
     /** If true, ignores the check to constructors. */
 90  
     private boolean mIgnoreConstructors;
 91  
     /** If true, ignore the check to methods. */
 92  
     private boolean mIgnoreMethods;
 93  
     /** If true, ignore the check to modifiers (fields, ...). */
 94  
     private boolean mIgnoreModifiers;
 95  
 
 96  
     @Override
 97  
     public int[] getDefaultTokens()
 98  
     {
 99  3
         return new int[] {
 100  
             TokenTypes.CTOR_DEF,
 101  
             TokenTypes.METHOD_DEF,
 102  
             TokenTypes.MODIFIERS,
 103  
             TokenTypes.OBJBLOCK,
 104  
         };
 105  
     }
 106  
 
 107  
     @Override
 108  
     public void visitToken(DetailAST aAST)
 109  
     {
 110  210
         final int parentType = aAST.getParent().getType();
 111  
         ScopeState state;
 112  
 
 113  210
         switch(aAST.getType()) {
 114  
         case TokenTypes.OBJBLOCK:
 115  15
             mScopeStates.push(new ScopeState());
 116  15
             break;
 117  
 
 118  
         case TokenTypes.CTOR_DEF:
 119  12
             if (parentType != TokenTypes.OBJBLOCK) {
 120  0
                 return;
 121  
             }
 122  
 
 123  12
             state = mScopeStates.peek();
 124  12
             if (state.mScopeState > STATE_CTOR_DEF) {
 125  6
                 if (!mIgnoreConstructors) {
 126  4
                     log(aAST, "declaration.order.constructor");
 127  
                 }
 128  
             }
 129  
             else {
 130  6
                 state.mScopeState = STATE_CTOR_DEF;
 131  
             }
 132  6
             break;
 133  
 
 134  
         case TokenTypes.METHOD_DEF:
 135  27
             state = mScopeStates.peek();
 136  27
             if (parentType != TokenTypes.OBJBLOCK) {
 137  0
                 return;
 138  
             }
 139  
 
 140  27
             if (state.mScopeState > STATE_METHOD_DEF) {
 141  0
                 if (!mIgnoreMethods) {
 142  0
                     log(aAST, "declaration.order.method");
 143  
                 }
 144  
             }
 145  
             else {
 146  27
                 state.mScopeState = STATE_METHOD_DEF;
 147  
             }
 148  27
             break;
 149  
 
 150  
         case TokenTypes.MODIFIERS:
 151  156
             if ((parentType != TokenTypes.VARIABLE_DEF)
 152  
                 || (aAST.getParent().getParent().getType()
 153  
                     != TokenTypes.OBJBLOCK))
 154  
             {
 155  69
                 return;
 156  
             }
 157  
 
 158  87
             state = mScopeStates.peek();
 159  87
             if (aAST.findFirstToken(TokenTypes.LITERAL_STATIC) != null) {
 160  75
                 if (state.mScopeState > STATE_STATIC_VARIABLE_DEF) {
 161  15
                     if (!mIgnoreModifiers
 162  
                         || state.mScopeState > STATE_INSTANCE_VARIABLE_DEF)
 163  
                     {
 164  13
                         log(aAST, "declaration.order.static");
 165  
                     }
 166  
                 }
 167  
                 else {
 168  60
                     state.mScopeState = STATE_STATIC_VARIABLE_DEF;
 169  
                 }
 170  
             }
 171  
             else {
 172  12
                 if (state.mScopeState > STATE_INSTANCE_VARIABLE_DEF) {
 173  6
                     log(aAST, "declaration.order.instance");
 174  
                 }
 175  6
                 else if (state.mScopeState == STATE_STATIC_VARIABLE_DEF) {
 176  6
                     state.mDeclarationAccess = Scope.PUBLIC;
 177  6
                     state.mScopeState = STATE_INSTANCE_VARIABLE_DEF;
 178  
                 }
 179  
             }
 180  
 
 181  87
             final Scope access = ScopeUtils.getScopeFromMods(aAST);
 182  87
             if (state.mDeclarationAccess.compareTo(access) > 0) {
 183  48
                 if (!mIgnoreModifiers) {
 184  32
                     log(aAST, "declaration.order.access");
 185  
                 }
 186  
             }
 187  
             else {
 188  39
                 state.mDeclarationAccess = access;
 189  
             }
 190  39
             break;
 191  
 
 192  
         default:
 193  
         }
 194  141
     }
 195  
 
 196  
     @Override
 197  
     public void leaveToken(DetailAST aAST)
 198  
     {
 199  210
         switch(aAST.getType()) {
 200  
         case TokenTypes.OBJBLOCK:
 201  15
             mScopeStates.pop();
 202  15
             break;
 203  
 
 204  
         default:
 205  
         }
 206  210
     }
 207  
 
 208  
     /**
 209  
      * Sets whether to ignore constructors.
 210  
      * @param aIgnoreConstructors whether to ignore constructors.
 211  
      */
 212  
     public void setIgnoreConstructors(boolean aIgnoreConstructors)
 213  
     {
 214  2
         mIgnoreConstructors = aIgnoreConstructors;
 215  2
     }
 216  
 
 217  
     /**
 218  
      * Sets whether to ignore methods.
 219  
      * @param aIgnoreMethods whether to ignore methods.
 220  
      */
 221  
     public void setIgnoreMethods(boolean aIgnoreMethods)
 222  
     {
 223  2
         mIgnoreMethods = aIgnoreMethods;
 224  2
     }
 225  
 
 226  
     /**
 227  
      * Sets whether to ignore modifiers.
 228  
      * @param aIgnoreModifiers whether to ignore modifiers.
 229  
      */
 230  
     public void setIgnoreModifiers(boolean aIgnoreModifiers)
 231  
     {
 232  2
         mIgnoreModifiers = aIgnoreModifiers;
 233  2
     }
 234  
 }