// =================================================================================================
// Copyright 2011 Twitter, Inc.
// -------------------------------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this work except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file, or at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =================================================================================================
package com.twitter.common.checkstyle;
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
* Utilities needed by custom checkstyle rules.
*
* @author Utkarsh Srivastava
*/
public final class CheckStyleUtils {
private CheckStyleUtils() {
// utility
}
/**
* Returns the message bundle to use for a custom rule. All built-in rules in checkstyle have
* a message bundle in the same package as that rule. This method returns the path to that
* bundle.
*
* @param parentBuiltInCheckClass The class of the built-in checkstyle rule that the custom rule
* ultimately derives from.
* @return Path to message bundle.
*/
public static String getMessageBundle(final Class<? extends Check> parentBuiltInCheckClass) {
String parentBuiltInCheckClassName = parentBuiltInCheckClass.getName();
// This code is copied from com.puppycrawl.tools.checkstyle.api.
// AbstractViolationReporter.java::getMessageBundle(String s)
// If that method were protected (and not package private) we could
// just invoke it
final int endIndex = parentBuiltInCheckClassName.lastIndexOf('.');
final String messages = "messages";
if (endIndex < 0) {
return messages;
}
final String packageName = parentBuiltInCheckClassName.substring(0, endIndex);
return packageName + "." + messages;
}
/**
* Checks to see if a method has the "@Override" annotation.
*
* @param aAST The AST to check.
* @return Whether the AST represents a method that has the annotation.
*/
public static boolean isOverrideMethod(DetailAST aAST) {
// Need it to be a method, cannot have an override on anything else.
// Must also have MODIFIERS token to hold the @Override
if ((TokenTypes.METHOD_DEF != aAST.getType())
|| (TokenTypes.MODIFIERS != aAST.getFirstChild().getType())) {
return false;
}
// Now loop over all nodes while they are annotations looking for
// an "@Override".
DetailAST node = aAST.getFirstChild().getFirstChild();
while ((null != node) && (TokenTypes.ANNOTATION == node.getType())) {
if ((node.getFirstChild().getType() == TokenTypes.AT)
&& (node.getFirstChild().getNextSibling().getType() == TokenTypes.IDENT)
&& ("Override".equals(node.getFirstChild().getNextSibling().getText()))) {
return true;
}
node = node.getNextSibling();
}
return false;
}
}