Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
MultipleVariableDeclarationsCheck
100%
29/29
96%
27/28
4.75
 
 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.TokenTypes;
 24  
 import com.puppycrawl.tools.checkstyle.checks.CheckUtils;
 25  
 
 26  
 /**
 27  
  * <p>
 28  
  * Checks that each variable declaration is in its own statement
 29  
  * and on its own line.
 30  
  * </p>
 31  
  * <p>
 32  
  * Rationale: <a
 33  
  * href="http://java.sun.com/docs/codeconv/html/CodeConventions.doc5.html#2991">
 34  
  * the SUN Code conventions chapter 6.1</a> recommends that
 35  
  * declarations should be one per line.
 36  
  * </p>
 37  
  * <p>
 38  
  * An example of how to configure the check is:
 39  
  * </p>
 40  
  * <pre>
 41  
  * &lt;module name="MultipleVariableDeclarations"/&gt;
 42  
  * </pre>
 43  
  * @author o_sukhodolsky
 44  
  */
 45  
 public class MultipleVariableDeclarationsCheck extends Check
 46  
 {
 47  
     /** Creates new instance of the check. */
 48  
     public MultipleVariableDeclarationsCheck()
 49  1
     {
 50  1
     }
 51  
 
 52  
     @Override
 53  
     public int[] getDefaultTokens()
 54  
     {
 55  1
         return new int[] {TokenTypes.VARIABLE_DEF};
 56  
     }
 57  
 
 58  
     @Override
 59  
     public void visitToken(DetailAST aAST)
 60  
     {
 61  15
         DetailAST nextNode = aAST.getNextSibling();
 62  15
         final boolean isCommaSeparated =
 63  
             ((nextNode != null) && (nextNode.getType() == TokenTypes.COMMA));
 64  
 
 65  15
         if (nextNode == null) {
 66  
             // no next statement - no check
 67  2
             return;
 68  
         }
 69  
 
 70  13
         if ((nextNode.getType() == TokenTypes.COMMA)
 71  
             || (nextNode.getType() == TokenTypes.SEMI))
 72  
         {
 73  6
             nextNode = nextNode.getNextSibling();
 74  
         }
 75  
 
 76  13
         if ((nextNode != null)
 77  
             && (nextNode.getType() == TokenTypes.VARIABLE_DEF))
 78  
         {
 79  10
             final DetailAST firstNode = CheckUtils.getFirstNode(aAST);
 80  10
             if (isCommaSeparated) {
 81  
                 // Check if the multiple variable declarations are in a
 82  
                 // for loop initializer. If they are, then no warning
 83  
                 // should be displayed. Declaring multiple variables in
 84  
                 // a for loop initializer is a good way to minimize
 85  
                 // variable scope. Refer Feature Request Id - 2895985
 86  
                 // for more details
 87  3
                 if (aAST.getParent().getType() != TokenTypes.FOR_INIT) {
 88  2
                     log(firstNode, "multiple.variable.declarations.comma");
 89  
                 }
 90  3
                 return;
 91  
             }
 92  
 
 93  7
             final DetailAST lastNode = getLastNode(aAST);
 94  7
             final DetailAST firstNextNode = CheckUtils.getFirstNode(nextNode);
 95  
 
 96  7
             if (firstNextNode.getLineNo() == lastNode.getLineNo()) {
 97  4
                 log(firstNode, "multiple.variable.declarations");
 98  
             }
 99  
         }
 100  
 
 101  10
     }
 102  
 
 103  
     /**
 104  
      * Finds sub-node for given node maximum (line, column) pair.
 105  
      * @param aNode the root of tree for search.
 106  
      * @return sub-node with maximum (line, column) pair.
 107  
      */
 108  
     private static DetailAST getLastNode(final DetailAST aNode)
 109  
     {
 110  57
         DetailAST currentNode = aNode;
 111  57
         DetailAST child = aNode.getFirstChild();
 112  107
         while (child != null) {
 113  50
             final DetailAST newNode = getLastNode(child);
 114  50
             if ((newNode.getLineNo() > currentNode.getLineNo())
 115  
                 || ((newNode.getLineNo() == currentNode.getLineNo())
 116  
                     && (newNode.getColumnNo() > currentNode.getColumnNo())))
 117  
             {
 118  27
                 currentNode = newNode;
 119  
             }
 120  50
             child = child.getNextSibling();
 121  50
         }
 122  
 
 123  57
         return currentNode;
 124  
     }
 125  
 }