/* * Copyright 2009-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License 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 org.codehaus.groovy.eclipse.editor.highlighting; import java.util.List; import groovyjarjarasm.asm.Opcodes; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; import org.codehaus.groovy.ast.AnnotationNode; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.FieldNode; import org.codehaus.groovy.ast.ImportNode; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.ast.Variable; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; import org.codehaus.groovy.ast.stmt.CatchStatement; import org.codehaus.groovy.ast.stmt.ForStatement; import org.codehaus.jdt.groovy.internal.compiler.ast.JDTNode; import org.eclipse.jdt.groovy.search.ITypeRequestor; import org.eclipse.jdt.groovy.search.VariableScope; import org.eclipse.jface.text.Position; /** * Assists with searching for kinds of references in Groovy files. * * @author Andrew Eisenberg * @created Aug 28, 2011 */ public abstract class SemanticReferenceRequestor implements ITypeRequestor { protected static Position getPosition(ASTNode node) { int start, length; if (node instanceof FieldNode || node instanceof MethodNode || node instanceof PropertyNode || (node instanceof ClassNode && ((ClassNode) node).getNameEnd() > 0)) { AnnotatedNode an = (AnnotatedNode) node; start = an.getNameStart(); length = an.getNameEnd() - start + 1; } else if (node instanceof Parameter) { Parameter p = (Parameter) node; start = p.getNameStart(); length = p.getNameEnd() - start; } else if (node instanceof ImportNode) { ClassNode clazz = ((ImportNode) node).getType(); start = clazz.getStart(); length = clazz.getLength(); } else if (node instanceof StaticMethodCallExpression) { start = node.getStart(); length = ((StaticMethodCallExpression) node).getMethod().length(); } else if (node instanceof MethodCallExpression) { Expression e = ((MethodCallExpression) node).getMethod(); // FIXADE : determine if we need to ignore funky method calls that // use things like GStrings in the // name // if (e instanceof ConstantExpression) { start = e.getStart(); length = e.getLength(); // } } else { start = node.getStart(); length = node.getLength(); } return new Position(start, length); } protected static boolean isDeprecated(ASTNode declaration) { if (declaration instanceof ClassNode) { declaration = ((ClassNode) declaration).redirect(); } if (declaration instanceof PropertyNode && ((PropertyNode) declaration).getField() != null) { // make sure we are using the associated field node because property nodes are never the declaration declaration = ((PropertyNode) declaration).getField(); } if (declaration instanceof JDTNode) { return ((JDTNode) declaration).isDeprecated(); } else if (declaration instanceof ClassNode || declaration instanceof FieldNode || declaration instanceof MethodNode) { return hasDeprecatedAnnotation((AnnotatedNode) declaration); } return false; } private static boolean hasDeprecatedAnnotation(AnnotatedNode declaration) { // only DSLDs will have the deprecation flag set if (isDeprecated(declaration)) { return true; } List<AnnotationNode> anns = declaration.getAnnotations(); for (AnnotationNode ann : anns) { if (ann.getClassNode() != null && ann.getClassNode().getName().equals("java.lang.Deprecated")) { return true; } } return false; } private static boolean isDeprecated(AnnotatedNode node) { int flags; if (node instanceof ClassNode) { flags = ((ClassNode) node).getModifiers(); } else if (node instanceof MethodNode) { flags = ((MethodNode) node).getModifiers(); } else if (node instanceof FieldNode) { flags = ((FieldNode) node).getModifiers(); } else { flags = 0; } return (flags & Opcodes.ACC_DEPRECATED) != 0; } protected static boolean isFinal(ASTNode node) { if (node instanceof FieldNode) { return ((FieldNode) node).isFinal(); } if (node instanceof MethodNode) { return (((MethodNode) node).getModifiers() & Opcodes.ACC_FINAL) != 0; } return false; } protected static boolean isForLoopParam(Variable param, VariableScope scope) { VariableScope.VariableInfo info = scope.lookupName(param.getName()); return (info != null && info.scopeNode instanceof ForStatement); } protected static boolean isCatchParam(Variable param, VariableScope scope) { VariableScope.VariableInfo info = scope.lookupName(param.getName()); return (info != null && info.scopeNode instanceof CatchStatement); } protected static boolean isNumber(ClassNode type) { return ClassHelper.isNumberType(type) || ClassHelper.BigDecimal_TYPE.equals(type) || ClassHelper.BigInteger_TYPE.equals(type); } protected static boolean isStatic(ASTNode node) { if (node instanceof FieldNode) { return ((FieldNode) node).isStatic(); } if (node instanceof MethodNode) { return ((MethodNode) node).isStatic(); } if (node instanceof PropertyNode) { return ((PropertyNode) node).isStatic(); } return false; } }