Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.IllegalThrowsCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
IllegalThrowsCheck
100%
32/32
100%
16/16
1.778
 
 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.checks.coding;
 21  
 
 22  
 import java.util.Arrays;
 23  
 import java.util.Collections;
 24  
 import java.util.Set;
 25  
 import java.util.stream.Collectors;
 26  
 
 27  
 import com.puppycrawl.tools.checkstyle.StatelessCheck;
 28  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 29  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 30  
 import com.puppycrawl.tools.checkstyle.api.FullIdent;
 31  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 32  
 import com.puppycrawl.tools.checkstyle.utils.AnnotationUtility;
 33  
 import com.puppycrawl.tools.checkstyle.utils.CheckUtils;
 34  
 
 35  
 /**
 36  
  * <p>
 37  
  * Throwing java.lang.Error or java.lang.RuntimeException
 38  
  * is almost never acceptable.
 39  
  * </p>
 40  
  * Check has following properties:
 41  
  * <p>
 42  
  * <b>illegalClassNames</b> - throw class names to reject.
 43  
  * </p>
 44  
  * <p>
 45  
  * <b>ignoredMethodNames</b> - names of methods to ignore.
 46  
  * </p>
 47  
  * <p>
 48  
  * <b>ignoreOverriddenMethods</b> - ignore checking overridden methods (marked with Override
 49  
  *  or java.lang.Override annotation) default value is <b>true</b>.
 50  
  * </p>
 51  
  *
 52  
  * @author Oliver Burn
 53  
  * @author John Sirois
 54  
  * @author <a href="mailto:nesterenko-aleksey@list.ru">Aleksey Nesterenko</a>
 55  
  */
 56  
 @StatelessCheck
 57  17
 public final class IllegalThrowsCheck extends AbstractCheck {
 58  
 
 59  
     /**
 60  
      * A key is pointing to the warning message text in "messages.properties"
 61  
      * file.
 62  
      */
 63  
     public static final String MSG_KEY = "illegal.throw";
 64  
 
 65  
     /** Methods which should be ignored. */
 66  17
     private final Set<String> ignoredMethodNames =
 67  17
         Arrays.stream(new String[] {"finalize", }).collect(Collectors.toSet());
 68  
 
 69  
     /** Illegal class names. */
 70  17
     private final Set<String> illegalClassNames = Arrays.stream(
 71  
         new String[] {"Error", "RuntimeException", "Throwable", "java.lang.Error",
 72  
                       "java.lang.RuntimeException", "java.lang.Throwable", })
 73  17
         .collect(Collectors.toSet());
 74  
 
 75  
     /** Property for ignoring overridden methods. */
 76  17
     private boolean ignoreOverriddenMethods = true;
 77  
 
 78  
     /**
 79  
      * Set the list of illegal classes.
 80  
      *
 81  
      * @param classNames
 82  
      *            array of illegal exception classes
 83  
      */
 84  
     public void setIllegalClassNames(final String... classNames) {
 85  3
         illegalClassNames.clear();
 86  6
         illegalClassNames.addAll(
 87  3
                 CheckUtils.parseClassNames(classNames));
 88  
 
 89  3
     }
 90  
 
 91  
     @Override
 92  
     public int[] getDefaultTokens() {
 93  27
         return getRequiredTokens();
 94  
     }
 95  
 
 96  
     @Override
 97  
     public int[] getRequiredTokens() {
 98  59
         return new int[] {TokenTypes.LITERAL_THROWS};
 99  
     }
 100  
 
 101  
     @Override
 102  
     public int[] getAcceptableTokens() {
 103  5
         return getRequiredTokens();
 104  
     }
 105  
 
 106  
     @Override
 107  
     public void visitToken(DetailAST detailAST) {
 108  20
         final DetailAST methodDef = detailAST.getParent();
 109  
         // Check if the method with the given name should be ignored.
 110  20
         if (!isIgnorableMethod(methodDef)) {
 111  14
             DetailAST token = detailAST.getFirstChild();
 112  32
             while (token != null) {
 113  18
                 if (token.getType() != TokenTypes.COMMA) {
 114  16
                     final FullIdent ident = FullIdent.createFullIdent(token);
 115  16
                     if (illegalClassNames.contains(ident.getText())) {
 116  11
                         log(token, MSG_KEY, ident.getText());
 117  
                     }
 118  
                 }
 119  18
                 token = token.getNextSibling();
 120  
             }
 121  
         }
 122  20
     }
 123  
 
 124  
     /**
 125  
      * Checks if current method is ignorable due to Check's properties.
 126  
      * @param methodDef {@link TokenTypes#METHOD_DEF METHOD_DEF}
 127  
      * @return true if method is ignorable.
 128  
      */
 129  
     private boolean isIgnorableMethod(DetailAST methodDef) {
 130  40
         return shouldIgnoreMethod(methodDef.findFirstToken(TokenTypes.IDENT).getText())
 131  
             || ignoreOverriddenMethods
 132  14
                && (AnnotationUtility.containsAnnotation(methodDef, "Override")
 133  13
                   || AnnotationUtility.containsAnnotation(methodDef, "java.lang.Override"));
 134  
     }
 135  
 
 136  
     /**
 137  
      * Check if the method is specified in the ignore method list.
 138  
      * @param name the name to check
 139  
      * @return whether the method with the passed name should be ignored
 140  
      */
 141  
     private boolean shouldIgnoreMethod(String name) {
 142  20
         return ignoredMethodNames.contains(name);
 143  
     }
 144  
 
 145  
     /**
 146  
      * Set the list of ignore method names.
 147  
      * @param methodNames array of ignored method names
 148  
      */
 149  
     public void setIgnoredMethodNames(String... methodNames) {
 150  3
         ignoredMethodNames.clear();
 151  3
         Collections.addAll(ignoredMethodNames, methodNames);
 152  3
     }
 153  
 
 154  
     /**
 155  
      * Sets <b>ignoreOverriddenMethods</b> property value.
 156  
      * @param ignoreOverriddenMethods Check's property.
 157  
      */
 158  
     public void setIgnoreOverriddenMethods(boolean ignoreOverriddenMethods) {
 159  3
         this.ignoreOverriddenMethods = ignoreOverriddenMethods;
 160  3
     }
 161  
 }