Coverage Report - com.puppycrawl.tools.checkstyle.utils.BlockCommentPosition
 
Classes in this File Line Coverage Branch Coverage Complexity
BlockCommentPosition
100%
60/60
100%
108/108
3.667
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2017 the original author or authors.
 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  
 
 20  
 package com.puppycrawl.tools.checkstyle.utils;
 21  
 
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 24  
 
 25  
 /**
 26  
  * Utility class that has methods to check javadoc comment position in java file.
 27  
  * @author bizmailov
 28  
  *
 29  
  */
 30  
 public final class BlockCommentPosition {
 31  
 
 32  
     /**
 33  
      * Forbid new instances.
 34  
      */
 35  1
     private BlockCommentPosition() {
 36  1
     }
 37  
 
 38  
     /**
 39  
      * Node is on class definition.
 40  
      * @param blockComment DetailAST
 41  
      * @return true if node is before class
 42  
      */
 43  
     public static boolean isOnClass(DetailAST blockComment) {
 44  3550
         return isOnPlainToken(blockComment, TokenTypes.CLASS_DEF, TokenTypes.LITERAL_CLASS)
 45  1722
                 || isOnTokenWithModifiers(blockComment, TokenTypes.CLASS_DEF)
 46  1703
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.CLASS_DEF);
 47  
     }
 48  
 
 49  
     /**
 50  
      * Node is on interface definition.
 51  
      * @param blockComment DetailAST
 52  
      * @return true if node is before interface
 53  
      */
 54  
     public static boolean isOnInterface(DetailAST blockComment) {
 55  3396
         return isOnPlainToken(blockComment, TokenTypes.INTERFACE_DEF, TokenTypes.LITERAL_INTERFACE)
 56  1689
                 || isOnTokenWithModifiers(blockComment, TokenTypes.INTERFACE_DEF)
 57  1681
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.INTERFACE_DEF);
 58  
     }
 59  
 
 60  
     /**
 61  
      * Node is on enum definition.
 62  
      * @param blockComment DetailAST
 63  
      * @return true if node is before enum
 64  
      */
 65  
     public static boolean isOnEnum(DetailAST blockComment) {
 66  3352
         return isOnPlainToken(blockComment, TokenTypes.ENUM_DEF, TokenTypes.ENUM)
 67  1667
                 || isOnTokenWithModifiers(blockComment, TokenTypes.ENUM_DEF)
 68  1659
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.ENUM_DEF);
 69  
     }
 70  
 
 71  
     /**
 72  
      * Node is on annotation definition.
 73  
      * @param blockComment DetailAST
 74  
      * @return true if node is before annotation
 75  
      */
 76  
     public static boolean isOnAnnotationDef(DetailAST blockComment) {
 77  2318
         return isOnPlainToken(blockComment, TokenTypes.ANNOTATION_DEF, TokenTypes.AT)
 78  1154
                 || isOnTokenWithModifiers(blockComment, TokenTypes.ANNOTATION_DEF)
 79  1149
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.ANNOTATION_DEF);
 80  
     }
 81  
 
 82  
     /**
 83  
      * Node is on method declaration.
 84  
      * @param blockComment DetailAST
 85  
      * @return true if node is before method
 86  
      */
 87  
     public static boolean isOnMethod(DetailAST blockComment) {
 88  3308
         return isOnPlainClassMember(blockComment, TokenTypes.METHOD_DEF)
 89  1417
                 || isOnTokenWithModifiers(blockComment, TokenTypes.METHOD_DEF)
 90  1352
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.METHOD_DEF);
 91  
     }
 92  
 
 93  
     /**
 94  
      * Node is on field declaration.
 95  
      * @param blockComment DetailAST
 96  
      * @return true if node is before field
 97  
      */
 98  
     public static boolean isOnField(DetailAST blockComment) {
 99  2694
         return isOnPlainClassMember(blockComment, TokenTypes.VARIABLE_DEF)
 100  1330
                 || isOnTokenWithModifiers(blockComment, TokenTypes.VARIABLE_DEF)
 101  1212
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.VARIABLE_DEF);
 102  
     }
 103  
 
 104  
     /**
 105  
      * Node is on constructor.
 106  
      * @param blockComment DetailAST
 107  
      * @return true if node is before constructor
 108  
      */
 109  
     public static boolean isOnConstructor(DetailAST blockComment) {
 110  2402
         return isOnPlainToken(blockComment, TokenTypes.CTOR_DEF, TokenTypes.IDENT)
 111  1196
                 || isOnTokenWithModifiers(blockComment, TokenTypes.CTOR_DEF)
 112  1184
                 || isOnTokenWithAnnotation(blockComment, TokenTypes.CTOR_DEF);
 113  
     }
 114  
 
 115  
     /**
 116  
      * Node is on enum constant.
 117  
      * @param blockComment DetailAST
 118  
      * @return true if node is before enum constant
 119  
      */
 120  
     public static boolean isOnEnumConstant(DetailAST blockComment) {
 121  1178
         final boolean isOnPlainConst = blockComment.getParent() != null
 122  1175
                 && blockComment.getParent().getType() == TokenTypes.ENUM_CONSTANT_DEF
 123  44
                 && getPrevSiblingSkipComments(blockComment).getType() == TokenTypes.ANNOTATIONS
 124  20
                 && getPrevSiblingSkipComments(blockComment).getChildCount() == 0;
 125  1178
         final boolean isOnConstWithAnnotation = !isOnPlainConst && blockComment.getParent() != null
 126  1161
                 && blockComment.getParent().getType() == TokenTypes.ANNOTATION
 127  48
                 && blockComment.getParent().getParent().getParent().getType()
 128  
                     == TokenTypes.ENUM_CONSTANT_DEF;
 129  1178
         return isOnPlainConst || isOnConstWithAnnotation;
 130  
     }
 131  
 
 132  
     /**
 133  
      * Checks that block comment is on specified token without any modifiers.
 134  
      * @param blockComment block comment start DetailAST
 135  
      * @param parentTokenType parent token type
 136  
      * @param nextTokenType next token type
 137  
      * @return true if block comment is on specified token without modifiers
 138  
      */
 139  
     private static boolean isOnPlainToken(DetailAST blockComment,
 140  
             int parentTokenType, int nextTokenType) {
 141  15018
         return blockComment.getParent() != null
 142  7494
                 && blockComment.getParent().getType() == parentTokenType
 143  252
                 && getPrevSiblingSkipComments(blockComment).getChildCount() == 0
 144  198
                 && getNextSiblingSkipComments(blockComment).getType() == nextTokenType;
 145  
     }
 146  
 
 147  
     /**
 148  
      * Checks that block comment is on specified token with modifiers.
 149  
      * @param blockComment block comment start DetailAST
 150  
      * @param tokenType parent token type
 151  
      * @return true if block comment is on specified token with modifiers
 152  
      */
 153  
     private static boolean isOnTokenWithModifiers(DetailAST blockComment, int tokenType) {
 154  20350
         return blockComment.getParent() != null
 155  10154
                 && blockComment.getParent().getType() == TokenTypes.MODIFIERS
 156  1541
                 && blockComment.getParent().getParent().getType() == tokenType
 157  313
                 && getPrevSiblingSkipComments(blockComment) == null;
 158  
     }
 159  
 
 160  
     /**
 161  
      * Checks that block comment is on specified token with annotation.
 162  
      * @param blockComment block comment start DetailAST
 163  
      * @param tokenType parent token type
 164  
      * @return true if block comment is on specified token with annotation
 165  
      */
 166  
     private static boolean isOnTokenWithAnnotation(DetailAST blockComment, int tokenType) {
 167  19880
         return blockComment.getParent() != null
 168  9919
                 && blockComment.getParent().getType() == TokenTypes.ANNOTATION
 169  506
                 && getPrevSiblingSkipComments(blockComment.getParent()) == null
 170  275
                 && blockComment.getParent().getParent().getType() == TokenTypes.MODIFIERS
 171  233
                 && blockComment.getParent().getParent().getParent().getType() == tokenType
 172  62
                 && getPrevSiblingSkipComments(blockComment) == null;
 173  
     }
 174  
 
 175  
     /**
 176  
      * Checks that block comment is on specified class member without any modifiers.
 177  
      * @param blockComment block comment start DetailAST
 178  
      * @param memberType parent token type
 179  
      * @return true if block comment is on specified token without modifiers
 180  
      */
 181  
     private static boolean isOnPlainClassMember(DetailAST blockComment, int memberType) {
 182  6002
         return blockComment.getParent() != null
 183  2995
                 && blockComment.getParent().getType() == TokenTypes.TYPE
 184  402
                 && blockComment.getParent().getParent().getType() == memberType
 185  
                 // previous parent sibling is always TokenTypes.MODIFIERS
 186  317
                 && blockComment.getParent().getPreviousSibling().getChildCount() == 0;
 187  
     }
 188  
 
 189  
     /**
 190  
      * Get next sibling node skipping any comment nodes.
 191  
      * @param node current node
 192  
      * @return next sibling
 193  
      */
 194  
     private static DetailAST getNextSiblingSkipComments(DetailAST node) {
 195  198
         DetailAST result = node.getNextSibling();
 196  208
         while (result.getType() == TokenTypes.SINGLE_LINE_COMMENT
 197  199
                 || result.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
 198  10
             result = result.getNextSibling();
 199  
         }
 200  198
         return result;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Get previous sibling node skipping any comments.
 205  
      * @param node current node
 206  
      * @return previous sibling
 207  
      */
 208  
     private static DetailAST getPrevSiblingSkipComments(DetailAST node) {
 209  1197
         DetailAST result = node.getPreviousSibling();
 210  1234
         while (result != null
 211  665
                 && (result.getType() == TokenTypes.SINGLE_LINE_COMMENT
 212  629
                 || result.getType() == TokenTypes.BLOCK_COMMENT_BEGIN)) {
 213  37
             result = result.getPreviousSibling();
 214  
         }
 215  1197
         return result;
 216  
     }
 217  
 }