All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.puppycrawl.tools.checkstyle.checks.annotation.MissingOverrideCheck Maven / Gradle / Ivy

Go to download

Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard

The newest version!
///////////////////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
// Copyright (C) 2001-2024 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
///////////////////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.checks.annotation;

import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import com.puppycrawl.tools.checkstyle.StatelessCheck;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagInfo;
import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;
import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;

/**
 * 
* Verifies that the {@code @Override} annotation is present * when the {@code @inheritDoc} javadoc tag is present. *
* *

* Rationale: The @Override annotation helps * compiler tools ensure that an override is actually occurring. It is * quite easy to accidentally overload a method or hide a static method * and using the @Override annotation points out these problems. *

* *

* This check will log a violation if using the @inheritDoc tag on a method that * is not valid (ex: private, or static method). *

* *

* There is a slight difference between the @Override annotation in Java 5 versus * Java 6 and above. In Java 5, any method overridden from an interface cannot * be annotated with @Override. In Java 6 this behavior is allowed. *

* *

* As a result of the aforementioned difference between Java 5 and Java 6, a * property called {@code javaFiveCompatibility} is available. This * property will only check classes, interfaces, etc. that do not contain the * extends or implements keyword or are not anonymous classes. This means it * only checks methods overridden from {@code java.lang.Object}. * Java 5 Compatibility mode severely limits this check. It is recommended to * only use it on Java 5 source. *

*
    *
  • * Property {@code javaFiveCompatibility} - Enable java 5 compatibility mode. * Type is {@code boolean}. * Default value is {@code false}. *
  • *
* *

* Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} *

* *

* Violation Message Keys: *

*
    *
  • * {@code annotation.missing.override} *
  • *
  • * {@code tag.not.valid.on} *
  • *
* * @since 5.0 */ @StatelessCheck public final class MissingOverrideCheck extends AbstractCheck { /** * A key is pointing to the warning message text in "messages.properties" * file. */ public static final String MSG_KEY_TAG_NOT_VALID_ON = "tag.not.valid.on"; /** * A key is pointing to the warning message text in "messages.properties" * file. */ public static final String MSG_KEY_ANNOTATION_MISSING_OVERRIDE = "annotation.missing.override"; /** Compiled regexp to match Javadoc tags with no argument and {}. */ private static final Pattern MATCH_INHERIT_DOC = CommonUtil.createPattern("\\{\\s*@(inheritDoc)\\s*\\}"); /** * Enable java 5 compatibility mode. */ private boolean javaFiveCompatibility; /** * Setter to enable java 5 compatibility mode. * * @param compatibility compatibility or not * @since 5.0 */ public void setJavaFiveCompatibility(final boolean compatibility) { javaFiveCompatibility = compatibility; } @Override public int[] getDefaultTokens() { return getRequiredTokens(); } @Override public int[] getAcceptableTokens() { return getRequiredTokens(); } @Override public boolean isCommentNodesRequired() { return true; } @Override public int[] getRequiredTokens() { return new int[] {TokenTypes.METHOD_DEF, }; } @Override public void visitToken(final DetailAST ast) { final boolean containsTag = containsInheritDocTag(ast); if (containsTag && !JavadocTagInfo.INHERIT_DOC.isValidOn(ast)) { log(ast, MSG_KEY_TAG_NOT_VALID_ON, JavadocTagInfo.INHERIT_DOC.getText()); } else { boolean check = true; if (javaFiveCompatibility) { final DetailAST defOrNew = ast.getParent().getParent(); if (defOrNew.findFirstToken(TokenTypes.EXTENDS_CLAUSE) != null || defOrNew.findFirstToken(TokenTypes.IMPLEMENTS_CLAUSE) != null || defOrNew.getType() == TokenTypes.LITERAL_NEW) { check = false; } } if (check && containsTag && !AnnotationUtil.hasOverrideAnnotation(ast)) { log(ast, MSG_KEY_ANNOTATION_MISSING_OVERRIDE); } } } /** * Checks to see if the ast contains a inheritDoc tag. * * @param ast method AST node * @return true if contains the tag */ private static boolean containsInheritDocTag(DetailAST ast) { final DetailAST modifiers = ast.getFirstChild(); final DetailAST startNode; if (modifiers.hasChildren()) { startNode = Optional.ofNullable(ast.getFirstChild() .findFirstToken(TokenTypes.ANNOTATION)) .orElse(modifiers); } else { startNode = ast.findFirstToken(TokenTypes.TYPE); } final Optional javadoc = Stream.iterate(startNode.getLastChild(), Objects::nonNull, DetailAST::getPreviousSibling) .filter(node -> node.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) .map(DetailAST::getFirstChild) .map(DetailAST::getText) .filter(JavadocUtil::isJavadocComment) .findFirst(); return javadoc.isPresent() && MATCH_INHERIT_DOC.matcher(javadoc.orElseThrow()).find(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy