/* * Copyright 2011 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.dsl.inferencing.suggestions; import java.util.List; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.ImportNode; import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.FieldExpression; import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; import org.codehaus.groovy.ast.expr.VariableExpression; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.ISourceReference; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.groovy.search.ITypeRequestor; import org.eclipse.jdt.groovy.search.TypeLookupResult; import org.eclipse.jdt.groovy.search.VariableScope; import org.eclipse.jdt.internal.core.NamedMember; import org.eclipse.jdt.internal.core.util.Util; /** * * * @author Nieraj Singh * @created 2011-09-13 */ public class SuggestionsRequestor implements ITypeRequestor { private final ASTNode nodeToLookFor; private SuggestionDescriptor descriptor; public SuggestionsRequestor(ASTNode nodeToLookFor) { this.nodeToLookFor = nodeToLookFor; } public VisitStatus acceptASTNode(ASTNode node, TypeLookupResult result, IJavaElement enclosingElement) { // check to see if the enclosing element does not enclose the // nodeToLookFor if (!interestingElement(enclosingElement)) { return VisitStatus.CANCEL_MEMBER; } if (node instanceof ImportNode) { node = ((ImportNode) node).getType(); if (node == null) { return VisitStatus.CONTINUE; } } if (isValidNode(node) && doTest(node)) { Expression expression = (Expression) node; descriptor = createDescriptor(expression, result); return VisitStatus.STOP_VISIT; } return VisitStatus.CONTINUE; } public SuggestionDescriptor getSuggestionDescriptor() { return descriptor; } protected SuggestionDescriptor createDescriptor(Expression suggestionNode, TypeLookupResult result) { // get the declaring type and type of the member ClassNode declaringTypeNode = result.declaringType; ClassNode suggestionTypeNode = result.type; VariableScope scope = result.scope; String declaringTypeName = declaringTypeNode.getName(); String suggestionType = suggestionTypeNode.getName(); Object suggestionName = suggestionNode instanceof ConstantExpression ? ((ConstantExpression) suggestionNode).getValue() : suggestionNode.getText(); String name = suggestionName instanceof String ? (String) suggestionName : null; // TODO: must figure out a way to determine if this is static. For now, // user has to remember // to set this correctly in the UI boolean isStatic = false; String javaDoc = null; boolean useNamedArguments = false; List<MethodParameter> parameters = null; boolean isMethod = isMethod(scope); boolean isActive = true; return isMethod ? new SuggestionDescriptor(declaringTypeName, isStatic, name, javaDoc, suggestionType, useNamedArguments, parameters, isActive) : new SuggestionDescriptor(declaringTypeName, isStatic, name, javaDoc, suggestionType, isActive); } protected boolean isMethod(VariableScope scope) { if (scope != null) { return scope.isMethodCall(); } return false; } protected boolean interestingElement(IJavaElement enclosingElement) { // the clinit is always interesting since the clinit contains static // initializers if (enclosingElement.getElementName().equals("<clinit>")) { return true; } if (enclosingElement instanceof NamedMember) { try { ISourceRange range = ((ISourceReference) enclosingElement).getSourceRange(); return range.getOffset() <= nodeToLookFor.getStart() && range.getOffset() + range.getLength() >= nodeToLookFor.getEnd(); } catch (JavaModelException e) { Util.log(e); } } return false; } private boolean doTest(ASTNode node) { return node.getClass() == nodeToLookFor.getClass() && nodeToLookFor.getStart() == node.getStart() && nodeToLookFor.getEnd() == node.getEnd(); } public static boolean isValidNode(ASTNode node) { return node instanceof VariableExpression || node instanceof StaticMethodCallExpression || node instanceof FieldExpression || node instanceof ConstantExpression; } }