Coverage Report - com.puppycrawl.tools.checkstyle.api.DetailAST
 
Classes in this File Line Coverage Branch Coverage Complexity
DetailAST
100%
150/150
100%
68/68
2.259
 
 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.api;
 21  
 
 22  
 import java.util.BitSet;
 23  
 
 24  
 import antlr.CommonASTWithHiddenTokens;
 25  
 import antlr.Token;
 26  
 import antlr.collections.AST;
 27  
 import com.puppycrawl.tools.checkstyle.utils.TokenUtils;
 28  
 
 29  
 /**
 30  
  * An extension of the CommonAST that records the line and column number.
 31  
  *
 32  
  * @author Oliver Burn
 33  
  * @author lkuehne
 34  
  * @see <a href="http://www.antlr.org/">ANTLR Website</a>
 35  
  * @noinspection FieldNotUsedInToString, SerializableHasSerializationMethods
 36  
  */
 37  7751941
 public final class DetailAST extends CommonASTWithHiddenTokens {
 38  
     private static final long serialVersionUID = -2580884815577559874L;
 39  
 
 40  
     /** Constant to indicate if not calculated the child count. */
 41  
     private static final int NOT_INITIALIZED = Integer.MIN_VALUE;
 42  
 
 43  
     /** The line number. **/
 44  1331828
     private int lineNo = NOT_INITIALIZED;
 45  
     /** The column number. **/
 46  1331828
     private int columnNo = NOT_INITIALIZED;
 47  
 
 48  
     /** Number of children. */
 49  1331828
     private int childCount = NOT_INITIALIZED;
 50  
     /** The parent token. */
 51  
     private DetailAST parent;
 52  
     /** Previous sibling. */
 53  
     private DetailAST previousSibling;
 54  
 
 55  
     /**
 56  
      * All token types in this branch.
 57  
      * Token 'x' (where x is an int) is in this branch
 58  
      * if branchTokenTypes.get(x) is true.
 59  
      */
 60  
     private BitSet branchTokenTypes;
 61  
 
 62  
     @Override
 63  
     public void initialize(Token tok) {
 64  981423
         super.initialize(tok);
 65  981423
         lineNo = tok.getLine();
 66  
 
 67  
         // expect columns to start @ 0
 68  981423
         columnNo = tok.getColumn() - 1;
 69  981423
     }
 70  
 
 71  
     @Override
 72  
     public void initialize(AST ast) {
 73  70500
         final DetailAST detailAst = (DetailAST) ast;
 74  70500
         setText(detailAst.getText());
 75  70500
         setType(detailAst.getType());
 76  70500
         lineNo = detailAst.getLineNo();
 77  70500
         columnNo = detailAst.getColumnNo();
 78  70500
         hiddenAfter = detailAst.getHiddenAfter();
 79  70500
         hiddenBefore = detailAst.getHiddenBefore();
 80  70500
     }
 81  
 
 82  
     @Override
 83  
     public void setFirstChild(AST ast) {
 84  520579
         clearBranchTokenTypes();
 85  520579
         clearChildCountCache(this);
 86  520579
         super.setFirstChild(ast);
 87  520579
         if (ast != null) {
 88  260122
             ((DetailAST) ast).setParent(this);
 89  
         }
 90  520579
     }
 91  
 
 92  
     @Override
 93  
     public void setNextSibling(AST ast) {
 94  711214
         clearBranchTokenTypes();
 95  711214
         clearChildCountCache(parent);
 96  711214
         super.setNextSibling(ast);
 97  711214
         if (ast != null && parent != null) {
 98  555726
             ((DetailAST) ast).setParent(parent);
 99  
         }
 100  711214
         if (ast != null) {
 101  669400
             ((DetailAST) ast).previousSibling = this;
 102  
         }
 103  711214
     }
 104  
 
 105  
     /**
 106  
      * Add previous sibling.
 107  
      * @param ast
 108  
      *        DetailAST object.
 109  
      */
 110  
     public void addPreviousSibling(DetailAST ast) {
 111  33737
         clearBranchTokenTypes();
 112  33737
         clearChildCountCache(parent);
 113  33737
         if (ast != null) {
 114  
             //parent is set in setNextSibling or parent.setFirstChild
 115  33734
             final DetailAST previousSiblingNode = previousSibling;
 116  
 
 117  33734
             if (previousSiblingNode != null) {
 118  31411
                 ast.previousSibling = previousSiblingNode;
 119  31411
                 previousSiblingNode.setNextSibling(ast);
 120  
             }
 121  2323
             else if (parent != null) {
 122  2089
                 parent.setFirstChild(ast);
 123  
             }
 124  
 
 125  33734
             ast.setNextSibling(this);
 126  33734
             previousSibling = ast;
 127  
         }
 128  33737
     }
 129  
 
 130  
     /**
 131  
      * Add next sibling.
 132  
      * @param ast
 133  
      *        DetailAST object.
 134  
      */
 135  
     public void addNextSibling(DetailAST ast) {
 136  28
         clearBranchTokenTypes();
 137  28
         clearChildCountCache(parent);
 138  28
         if (ast != null) {
 139  
             //parent is set in setNextSibling
 140  25
             final DetailAST nextSibling = getNextSibling();
 141  
 
 142  25
             if (nextSibling != null) {
 143  2
                 ast.setNextSibling(nextSibling);
 144  2
                 nextSibling.previousSibling = ast;
 145  
             }
 146  
 
 147  25
             ast.previousSibling = this;
 148  25
             setNextSibling(ast);
 149  
         }
 150  28
     }
 151  
 
 152  
     @Override
 153  
     public void addChild(AST ast) {
 154  353597
         clearBranchTokenTypes();
 155  353597
         clearChildCountCache(this);
 156  353597
         if (ast != null) {
 157  279865
             ((DetailAST) ast).setParent(this);
 158  279865
             ((DetailAST) ast).previousSibling = getLastChild();
 159  
         }
 160  353597
         super.addChild(ast);
 161  353597
     }
 162  
 
 163  
     /**
 164  
      * Returns the number of child nodes one level below this node. That is is
 165  
      * does not recurse down the tree.
 166  
      * @return the number of child nodes
 167  
      */
 168  
     public int getChildCount() {
 169  
         // lazy init
 170  2757
         if (childCount == NOT_INITIALIZED) {
 171  2568
             childCount = 0;
 172  2568
             AST child = getFirstChild();
 173  
 
 174  5062
             while (child != null) {
 175  2494
                 childCount += 1;
 176  2494
                 child = child.getNextSibling();
 177  
             }
 178  
         }
 179  2757
         return childCount;
 180  
     }
 181  
 
 182  
     /**
 183  
      * Returns the number of direct child tokens that have the specified type.
 184  
      * @param type the token type to match
 185  
      * @return the number of matching token
 186  
      */
 187  
     public int getChildCount(int type) {
 188  207
         int count = 0;
 189  886
         for (AST ast = getFirstChild(); ast != null; ast = ast.getNextSibling()) {
 190  679
             if (ast.getType() == type) {
 191  210
                 count++;
 192  
             }
 193  
         }
 194  207
         return count;
 195  
     }
 196  
 
 197  
     /**
 198  
      * Set the parent token.
 199  
      * @param parent the parent token
 200  
      */
 201  
     private void setParent(DetailAST parent) {
 202  1095731
         DetailAST instance = this;
 203  
         do {
 204  451215054
             instance.clearBranchTokenTypes();
 205  451215054
             instance.parent = parent;
 206  451215054
             final DetailAST nextSibling = instance.getNextSibling();
 207  451215054
             if (nextSibling != null) {
 208  450119323
                 nextSibling.previousSibling = instance;
 209  
             }
 210  
 
 211  451215054
             instance = nextSibling;
 212  451215054
         } while (instance != null);
 213  1095731
     }
 214  
 
 215  
     /**
 216  
      * Returns the parent token.
 217  
      * @return the parent token
 218  
      */
 219  
     public DetailAST getParent() {
 220  1409722
         return parent;
 221  
     }
 222  
 
 223  
     /**
 224  
      * Gets line number.
 225  
      * @return the line number
 226  
      */
 227  
     public int getLineNo() {
 228  4171529
         int resultNo = -1;
 229  
 
 230  4171529
         if (lineNo == NOT_INITIALIZED) {
 231  
             // an inner AST that has been initialized
 232  
             // with initialize(String text)
 233  1067040
             resultNo = findLineNo(getFirstChild());
 234  
 
 235  1067040
             if (resultNo == -1) {
 236  215903
                 resultNo = findLineNo(getNextSibling());
 237  
             }
 238  
         }
 239  4171529
         if (resultNo == -1) {
 240  3113008
             resultNo = lineNo;
 241  
         }
 242  4171529
         return resultNo;
 243  
     }
 244  
 
 245  
     /**
 246  
      * Set line number.
 247  
      * @param lineNo
 248  
      *        line number.
 249  
      */
 250  
     public void setLineNo(int lineNo) {
 251  70286
         this.lineNo = lineNo;
 252  70286
     }
 253  
 
 254  
     /**
 255  
      * Gets column number.
 256  
      * @return the column number
 257  
      */
 258  
     public int getColumnNo() {
 259  3638489
         int resultNo = -1;
 260  
 
 261  3638489
         if (columnNo == NOT_INITIALIZED) {
 262  
             // an inner AST that has been initialized
 263  
             // with initialize(String text)
 264  908389
             resultNo = findColumnNo(getFirstChild());
 265  
 
 266  908389
             if (resultNo == -1) {
 267  180667
                 resultNo = findColumnNo(getNextSibling());
 268  
             }
 269  
         }
 270  3638489
         if (resultNo == -1) {
 271  2738620
             resultNo = columnNo;
 272  
         }
 273  3638489
         return resultNo;
 274  
     }
 275  
 
 276  
     /**
 277  
      * Set column number.
 278  
      * @param columnNo
 279  
      *        column number.
 280  
      */
 281  
     public void setColumnNo(int columnNo) {
 282  70285
         this.columnNo = columnNo;
 283  70285
     }
 284  
 
 285  
     /**
 286  
      * Gets the last child node.
 287  
      * @return the last child node
 288  
      */
 289  
     public DetailAST getLastChild() {
 290  284895
         DetailAST ast = getFirstChild();
 291  312973
         while (ast != null && ast.getNextSibling() != null) {
 292  28078
             ast = ast.getNextSibling();
 293  
         }
 294  284895
         return ast;
 295  
     }
 296  
 
 297  
     /**
 298  
      * Finds column number in the first non-comment node.
 299  
      *
 300  
      * @param ast DetailAST node.
 301  
      * @return Column number if non-comment node exists, -1 otherwise.
 302  
      */
 303  
     private static int findColumnNo(DetailAST ast) {
 304  1089056
         int resultNo = -1;
 305  1089056
         DetailAST node = ast;
 306  1091028
         while (node != null) {
 307  
             // comment node can't be start of any java statement/definition
 308  901841
             if (TokenUtils.isCommentType(node.getType())) {
 309  1972
                 node = node.getNextSibling();
 310  
             }
 311  
             else {
 312  899869
                 resultNo = node.getColumnNo();
 313  899869
                 break;
 314  
             }
 315  
         }
 316  1089056
         return resultNo;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Finds line number in the first non-comment node.
 321  
      *
 322  
      * @param ast DetailAST node.
 323  
      * @return Line number if non-comment node exists, -1 otherwise.
 324  
      */
 325  
     private static int findLineNo(DetailAST ast) {
 326  1282943
         int resultNo = -1;
 327  1282943
         DetailAST node = ast;
 328  1289635
         while (node != null) {
 329  
             // comment node can't be start of any java statement/definition
 330  1065213
             if (TokenUtils.isCommentType(node.getType())) {
 331  6692
                 node = node.getNextSibling();
 332  
             }
 333  
             else {
 334  1058521
                 resultNo = node.getLineNo();
 335  1058521
                 break;
 336  
             }
 337  
         }
 338  1282943
         return resultNo;
 339  
     }
 340  
 
 341  
     /**
 342  
      * Returns token type with branch.
 343  
      * @return the token types that occur in the branch as a sorted set.
 344  
      */
 345  
     private BitSet getBranchTokenTypes() {
 346  
         // lazy init
 347  5308
         if (branchTokenTypes == null) {
 348  
 
 349  4721
             branchTokenTypes = new BitSet();
 350  4721
             branchTokenTypes.set(getType());
 351  
 
 352  
             // add union of all children
 353  4721
             DetailAST child = getFirstChild();
 354  8667
             while (child != null) {
 355  3946
                 final BitSet childTypes = child.getBranchTokenTypes();
 356  3946
                 branchTokenTypes.or(childTypes);
 357  
 
 358  3946
                 child = child.getNextSibling();
 359  3946
             }
 360  
         }
 361  5308
         return branchTokenTypes;
 362  
     }
 363  
 
 364  
     /**
 365  
      * Checks if this branch of the parse tree contains a token
 366  
      * of the provided type.
 367  
      * @param type a TokenType
 368  
      * @return true if and only if this branch (including this node)
 369  
      *     contains a token of type {@code type}.
 370  
      */
 371  
     public boolean branchContains(int type) {
 372  1350
         return getBranchTokenTypes().get(type);
 373  
     }
 374  
 
 375  
     /**
 376  
      * Returns the previous sibling or null if no such sibling exists.
 377  
      * @return the previous sibling or null if no such sibling exists.
 378  
      */
 379  
     public DetailAST getPreviousSibling() {
 380  410112
         return previousSibling;
 381  
     }
 382  
 
 383  
     /**
 384  
      * Returns the first child token that makes a specified type.
 385  
      * @param type the token type to match
 386  
      * @return the matching token, or null if no match
 387  
      */
 388  
     public DetailAST findFirstToken(int type) {
 389  82761
         DetailAST returnValue = null;
 390  234796
         for (DetailAST ast = getFirstChild(); ast != null; ast = ast.getNextSibling()) {
 391  206349
             if (ast.getType() == type) {
 392  54314
                 returnValue = ast;
 393  54314
                 break;
 394  
             }
 395  
         }
 396  82761
         return returnValue;
 397  
     }
 398  
 
 399  
     @Override
 400  
     public String toString() {
 401  2464036
         return super.toString() + "[" + getLineNo() + "x" + getColumnNo() + "]";
 402  
     }
 403  
 
 404  
     @Override
 405  
     public DetailAST getNextSibling() {
 406  458778598
         return (DetailAST) super.getNextSibling();
 407  
     }
 408  
 
 409  
     @Override
 410  
     public DetailAST getFirstChild() {
 411  4636659
         return (DetailAST) super.getFirstChild();
 412  
     }
 413  
 
 414  
     /**
 415  
      * Clears the child count for the ast instance.
 416  
      * @param ast The ast to clear.
 417  
      */
 418  
     private static void clearChildCountCache(DetailAST ast) {
 419  1619155
         if (ast != null) {
 420  1463416
             ast.childCount = NOT_INITIALIZED;
 421  
         }
 422  1619155
     }
 423  
 
 424  
     /**
 425  
      * Clears branchTokenTypes cache for all parents of the current DetailAST instance, and the
 426  
      * child count for the current DetailAST instance.
 427  
      */
 428  
     private void clearBranchTokenTypes() {
 429  452834209
         DetailAST prevParent = parent;
 430  1353665105
         while (prevParent != null) {
 431  900830896
             prevParent.branchTokenTypes = null;
 432  900830896
             prevParent = prevParent.parent;
 433  
         }
 434  452834209
     }
 435  
 }