Coverage Report - com.puppycrawl.tools.checkstyle.checks.annotation.MissingOverrideCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
MissingOverrideCheck
96%
26/27
100%
24/24
3.667
 
 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.annotation;
 20  
 
 21  
 import java.util.regex.Matcher;
 22  
 import java.util.regex.Pattern;
 23  
 
 24  
 import com.puppycrawl.tools.checkstyle.api.AnnotationUtility;
 25  
 import com.puppycrawl.tools.checkstyle.api.Check;
 26  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 27  
 import com.puppycrawl.tools.checkstyle.api.JavadocTagInfo;
 28  
 import com.puppycrawl.tools.checkstyle.api.TextBlock;
 29  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 30  
 import com.puppycrawl.tools.checkstyle.api.Utils;
 31  
 
 32  
 /**
 33  
  * <p>
 34  
  * This class is used to verify that the {@link java.lang.Override Override}
 35  
  * annotation is present when the inheritDoc javadoc tag is present.
 36  
  * </p>
 37  
  *
 38  
  * <p>
 39  
  * Rationale: The {@link java.lang.Override Override} annotation helps
 40  
  * compiler tools ensure that an override is actually occurring.  It is
 41  
  * quite easy to accidentally overload a method or hide a static method
 42  
  * and using the {@link java.lang.Override Override} annotation points
 43  
  * out these problems.
 44  
  * </p>
 45  
  *
 46  
  * <p>
 47  
  * This check will log a violation if using the inheritDoc tag on a method that
 48  
  * is not valid (ex: private, or static method).
 49  
  * </p>
 50  
  *
 51  
  * <p>
 52  
  * There is a slight difference between the Override annotation in Java 5 versus
 53  
  * Java 6 and above. In Java 5, any method overridden from an interface cannot
 54  
  * be annotated with Override. In Java 6 this behavior is allowed.
 55  
  * </p>
 56  
  *
 57  
  * <p>
 58  
  * As a result of the aforementioned difference between Java 5 and Java 6, a
 59  
  * property called <code> javaFiveCompatibility </code> is available. This
 60  
  * property will only check classes, interfaces, etc. that do not contain the
 61  
  * extends or implements keyword or are not anonymous classes. This means it
 62  
  * only checks methods overridden from <code>java.lang.Object</code>
 63  
  *
 64  
  * <b>Java 5 Compatibility mode severely limits this check. It is recommended to
 65  
  * only use it on Java 5 source</b>
 66  
  * </p>
 67  
  *
 68  
  * <pre>
 69  
  * &lt;module name=&quot;MissingOverride&quot;&gt;
 70  
  *    &lt;property name=&quot;javaFiveCompatibility&quot;
 71  
  *        value=&quot;true&quot;/&gt;
 72  
  * &lt;/module&gt;
 73  
  * </pre>
 74  
  *
 75  
  * @author Travis Schneeberger
 76  
  */
 77  13
 public final class MissingOverrideCheck extends Check
 78  
 {
 79  
     /** {@link Override Override} annotation name */
 80  
     private static final String OVERRIDE = "Override";
 81  
 
 82  
     /** fully-qualified {@link Override Override} annotation name */
 83  
     private static final String FQ_OVERRIDE = "java.lang." + OVERRIDE;
 84  
 
 85  
     /** compiled regexp to match Javadoc tags with no argument and {} * */
 86  1
     private static final Pattern MATCH_INHERITDOC =
 87  
         Utils.createPattern("\\{\\s*@(inheritDoc)\\s*\\}");
 88  
 
 89  
     /** @see MissingDeprecatedCheck#setJavaFiveCompatibility(boolean) */
 90  
     private boolean mJavaFiveCompatibility;
 91  
 
 92  
     /**
 93  
      * Sets Java 5 compatibility mode.
 94  
      *
 95  
      * <p>
 96  
      * In Java 5, this check could flag code that is not valid for the Override
 97  
      * annotation even though it is a proper override. See the class
 98  
      * documentation for more information.
 99  
      * </p>
 100  
      *
 101  
      * <p>
 102  
      * Set this to true to turn on Java 5 compatibility mode. Set this to
 103  
      * false to turn off Java 5 compatibility mode.
 104  
      * </p>
 105  
      *
 106  
      * @param aCompatibility compatibility or not
 107  
      */
 108  
     public void setJavaFiveCompatibility(final boolean aCompatibility)
 109  
     {
 110  8
         this.mJavaFiveCompatibility = aCompatibility;
 111  8
     }
 112  
 
 113  
     /** {@inheritDoc} */
 114  
     @Override
 115  
     public int[] getDefaultTokens()
 116  
     {
 117  13
         return this.getRequiredTokens();
 118  
     }
 119  
 
 120  
     /** {@inheritDoc} */
 121  
     @Override
 122  
     public int[] getAcceptableTokens()
 123  
     {
 124  0
         return this.getRequiredTokens();
 125  
     }
 126  
 
 127  
     /** {@inheritDoc} */
 128  
     @Override
 129  
     public int[] getRequiredTokens()
 130  
     {
 131  13
         return new int[]
 132  
         {TokenTypes.METHOD_DEF, };
 133  
     }
 134  
 
 135  
     /** {@inheritDoc} */
 136  
     @Override
 137  
     public void visitToken(final DetailAST aAST)
 138  
     {
 139  91
         final TextBlock javadoc =
 140  
             this.getFileContents().getJavadocBefore(aAST.getLineNo());
 141  
 
 142  
 
 143  91
         final boolean containsTag = this.containsJavadocTag(javadoc);
 144  91
         if (containsTag && !JavadocTagInfo.INHERIT_DOC.isValidOn(aAST)) {
 145  2
             this.log(aAST.getLineNo(), "tag.not.valid.on",
 146  
                 JavadocTagInfo.INHERIT_DOC.getText());
 147  2
             return;
 148  
         }
 149  
 
 150  89
         if (this.mJavaFiveCompatibility) {
 151  44
             final DetailAST defOrNew = aAST.getParent().getParent();
 152  
 
 153  44
             if (defOrNew.branchContains(TokenTypes.EXTENDS_CLAUSE)
 154  
                 || defOrNew.branchContains(TokenTypes.IMPLEMENTS_CLAUSE)
 155  
                 || defOrNew.getType() == TokenTypes.LITERAL_NEW)
 156  
             {
 157  28
                 return;
 158  
             }
 159  
         }
 160  
 
 161  61
         if (containsTag
 162  
             && (!AnnotationUtility.containsAnnotation(aAST, OVERRIDE)
 163  
             && !AnnotationUtility.containsAnnotation(aAST, FQ_OVERRIDE)))
 164  
         {
 165  19
             this.log(aAST.getLineNo(), "annotation.missing.override");
 166  
         }
 167  61
     }
 168  
 
 169  
     /**
 170  
      * Checks to see if the text block contains a inheritDoc tag.
 171  
      *
 172  
      * @param aJavadoc the javadoc of the AST
 173  
      * @return true if contains the tag
 174  
      */
 175  
     private boolean containsJavadocTag(final TextBlock aJavadoc)
 176  
     {
 177  91
         if (aJavadoc == null) {
 178  27
             return false;
 179  
         }
 180  
 
 181  64
         final String[] lines = aJavadoc.getText();
 182  
 
 183  152
         for (final String line : lines) {
 184  148
             final Matcher matchInheritDoc =
 185  
                 MissingOverrideCheck.MATCH_INHERITDOC.matcher(line);
 186  
 
 187  148
             if (matchInheritDoc.find()) {
 188  60
                 return true;
 189  
             }
 190  
         }
 191  4
         return false;
 192  
     }
 193  
 }