Coverage Report - com.puppycrawl.tools.checkstyle.checks.modifier.ModifierOrderCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
ModifierOrderCheck
94%
32/34
92%
26/28
7.333
 
 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.modifier;
 20  
 
 21  
 import com.google.common.collect.Lists;
 22  
 import com.puppycrawl.tools.checkstyle.api.Check;
 23  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 24  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 
 28  
 /**
 29  
  * <p>
 30  
  * Checks that the order of modifiers conforms to the suggestions in the
 31  
  * <a
 32  
  * href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html">
 33  
  * Java Language specification, sections 8.1.1, 8.3.1 and 8.4.3</a>.
 34  
  * The correct order is:</p>
 35  
 
 36  
 <ol>
 37  
   <li><span class="code">public</span></li>
 38  
   <li><span class="code">protected</span></li>
 39  
 
 40  
   <li><span class="code">private</span></li>
 41  
   <li><span class="code">abstract</span></li>
 42  
   <li><span class="code">static</span></li>
 43  
   <li><span class="code">final</span></li>
 44  
   <li><span class="code">transient</span></li>
 45  
   <li><span class="code">volatile</span></li>
 46  
 
 47  
   <li><span class="code">synchronized</span></li>
 48  
   <li><span class="code">native</span></li>
 49  
   <li><span class="code">strictfp</span></li>
 50  
 </ol>
 51  
  * In additional, modifiers are checked to ensure all annotations
 52  
  * are declared before all other modifiers.
 53  
  * <p>
 54  
  * Rationale: Code is easier to read if everybody follows
 55  
  * a standard.
 56  
  * </p>
 57  
  * <p>
 58  
  * An example of how to configure the check is:
 59  
  * </p>
 60  
  * <pre>
 61  
  * &lt;module name="ModifierOrder"/&gt;
 62  
  * </pre>
 63  
  * @author Lars Kühne
 64  
  */
 65  1
 public class ModifierOrderCheck
 66  
     extends Check
 67  
 {
 68  
     /**
 69  
      * The order of modifiers as suggested in sections 8.1.1,
 70  
      * 8.3.1 and 8.4.3 of the JLS.
 71  
      */
 72  1
     private static final String[] JLS_ORDER =
 73  
     {
 74  
         "public", "protected", "private", "abstract", "static", "final",
 75  
         "transient", "volatile", "synchronized", "native", "strictfp",
 76  
     };
 77  
 
 78  
     @Override
 79  
     public int[] getDefaultTokens()
 80  
     {
 81  1
         return new int[] {TokenTypes.MODIFIERS};
 82  
     }
 83  
 
 84  
     @Override
 85  
     public void visitToken(DetailAST aAST)
 86  
     {
 87  32
         final List<DetailAST> mods = Lists.newArrayList();
 88  32
         DetailAST modifier = aAST.getFirstChild();
 89  70
         while (modifier != null) {
 90  38
             mods.add(modifier);
 91  38
             modifier = modifier.getNextSibling();
 92  
         }
 93  
 
 94  32
         if (!mods.isEmpty()) {
 95  23
             final DetailAST error = checkOrderSuggestedByJLS(mods);
 96  23
             if (error != null) {
 97  6
                 if (error.getType() == TokenTypes.ANNOTATION) {
 98  3
                     log(error.getLineNo(), error.getColumnNo(),
 99  
                             "annotation.order",
 100  
                              error.getFirstChild().getText()
 101  
                              + error.getFirstChild().getNextSibling()
 102  
                                 .getText());
 103  
                 }
 104  
                 else {
 105  3
                     log(error.getLineNo(), error.getColumnNo(),
 106  
                             "mod.order", error.getText());
 107  
                 }
 108  
             }
 109  
         }
 110  32
     }
 111  
 
 112  
 
 113  
     /**
 114  
      * Checks if the modifiers were added in the order suggested
 115  
      * in the Java language specification.
 116  
      *
 117  
      * @param aModifiers list of modifier AST tokens
 118  
      * @return null if the order is correct, otherwise returns the offending
 119  
      * *       modifier AST.
 120  
      */
 121  
     DetailAST checkOrderSuggestedByJLS(List<DetailAST> aModifiers)
 122  
     {
 123  23
         int i = 0;
 124  
         DetailAST modifier;
 125  23
         final Iterator<DetailAST> it = aModifiers.iterator();
 126  
         //No modifiers, no problems
 127  23
         if (!it.hasNext()) {
 128  0
             return null;
 129  
         }
 130  
 
 131  
         //Speed past all initial annotations
 132  
         do {
 133  25
             modifier = it.next();
 134  
         }
 135  25
         while (it.hasNext() && (modifier.getType() == TokenTypes.ANNOTATION));
 136  
 
 137  
         //All modifiers are annotations, no problem
 138  23
         if (modifier.getType() == TokenTypes.ANNOTATION) {
 139  1
             return null;
 140  
         }
 141  
 
 142  33
         while (i < JLS_ORDER.length) {
 143  33
             if (modifier.getType() == TokenTypes.ANNOTATION) {
 144  
                 //Annotation not at start of modifiers, bad
 145  3
                 return modifier;
 146  
             }
 147  
 
 148  
             while ((i < JLS_ORDER.length)
 149  120
                    && !JLS_ORDER[i].equals(modifier.getText()))
 150  
             {
 151  90
                 i++;
 152  
             }
 153  
 
 154  30
             if (i == JLS_ORDER.length) {
 155  
                 //Current modifier is out of JLS order
 156  3
                 return modifier;
 157  
             }
 158  27
             else if (!it.hasNext()) {
 159  
                 //Reached end of modifiers without problem
 160  16
                 return null;
 161  
             }
 162  
             else {
 163  11
                 modifier = it.next();
 164  
             }
 165  
         }
 166  
 
 167  0
         return modifier;
 168  
     }
 169  
 }