001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.java.ast.visitor;
021
022 import org.sonar.squid.api.AnalysisException;
023 import org.sonar.squid.api.SourceCode;
024
025 import antlr.collections.AST;
026
027 import com.puppycrawl.tools.checkstyle.api.DetailAST;
028 import com.puppycrawl.tools.checkstyle.api.Scope;
029 import com.puppycrawl.tools.checkstyle.api.ScopeUtils;
030 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
031
032 public final class AstUtils {
033
034 private AstUtils() {
035 }
036
037 public static AST findType(DetailAST ast) {
038 DetailAST typeAst = ast.findFirstToken(TokenTypes.TYPE);
039 if (typeAst != null) {
040 return typeAst.getFirstChild();
041 }
042 return null;
043 }
044
045 public static boolean isClassVariable(DetailAST ast) {
046 return ast.getType() == TokenTypes.VARIABLE_DEF && ast.getParent().getType() == TokenTypes.OBJBLOCK
047 && isClass(ast.getParent().getParent());
048 }
049
050 public static boolean isClass(DetailAST ast) {
051 return ast.getType() == TokenTypes.CLASS_DEF || ast.getType() == TokenTypes.ENUM_DEF || ast.getType() == TokenTypes.ANNOTATION_DEF
052 || ast.getType() == TokenTypes.INTERFACE_DEF;
053 }
054
055 public static boolean isInterfaceVariable(DetailAST ast) {
056 return ast.getType() == TokenTypes.VARIABLE_DEF && ast.getParent().getType() == TokenTypes.OBJBLOCK
057 && isInterface(ast.getParent().getParent());
058 }
059
060 public static boolean isInterface(DetailAST ast) {
061 return ast.getType() == TokenTypes.INTERFACE_DEF;
062 }
063
064 public static boolean isFinal(DetailAST detailAst) {
065 return isModifier(detailAst, TokenTypes.FINAL);
066 }
067
068 public static boolean isStatic(DetailAST detailAst) {
069 return isModifier(detailAst, TokenTypes.LITERAL_STATIC);
070 }
071
072 public static boolean isModifier(DetailAST detailAst, int modifierType) {
073 DetailAST modifiers = detailAst.findFirstToken(TokenTypes.MODIFIERS);
074 if (modifiers != null) {
075 boolean isModifierMatching = modifiers.branchContains(modifierType);
076 if (!isModifierMatching && isInterfaceVariable(detailAst)) {
077 // by default if not specified, a var def in an interface is
078 // public final static
079 return (modifierType == TokenTypes.LITERAL_STATIC || modifierType == TokenTypes.FINAL);
080 }
081 return isModifierMatching;
082 }
083 return false;
084 }
085
086 public static Scope getScope(DetailAST ast) {
087 DetailAST modifierAst = ast.findFirstToken(TokenTypes.MODIFIERS);
088 Scope found = modifierAst != null ? ScopeUtils.getScopeFromMods(modifierAst) : Scope.NOTHING;
089 if (found.compareTo(Scope.PACKAGE) == 0 && (ast.getType() == TokenTypes.METHOD_DEF || ast.getType() == TokenTypes.VARIABLE_DEF)) {
090 // check if we found a parent interface declaration
091 // interface methods or var defs are by default public when not
092 // specified
093 found = (isScope(Scope.PACKAGE, found) && findParent(ast, TokenTypes.INTERFACE_DEF) != null) ? Scope.PUBLIC : found;
094 }
095 return found;
096 }
097
098 public static boolean isScope(Scope toCompare, Scope scope) {
099 return scope.compareTo(toCompare) == 0;
100 }
101
102 public static boolean isType(DetailAST ast, int type) {
103 return ast.getType() == type;
104 }
105
106 public static DetailAST findParent(DetailAST ast, int tokenType) {
107 DetailAST parent = ast.getParent();
108 if (parent != null) {
109 return parent.getType() == tokenType ? parent : findParent(parent, tokenType);
110 }
111 return null;
112 }
113
114 public static void ensureResourceType(SourceCode resource, Class<? extends SourceCode> resourceType) {
115 if (!resource.isType(resourceType)) {
116 throw new AnalysisException("Resource " + resource.getKey() + " must be of type " + resourceType.getName());
117 }
118 }
119 }