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 */ 020package org.sonar.java.ast.visitor; 021 022import org.sonar.squid.api.AnalysisException; 023import org.sonar.squid.api.SourceCode; 024 025import antlr.collections.AST; 026 027import com.puppycrawl.tools.checkstyle.api.DetailAST; 028import com.puppycrawl.tools.checkstyle.api.Scope; 029import com.puppycrawl.tools.checkstyle.api.ScopeUtils; 030import com.puppycrawl.tools.checkstyle.api.TokenTypes; 031 032public 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}