/*
* Copyright 2009-2016 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.eclipse.jdt.groovy.search;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotationNode;
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.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.GStringExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.eclipse.jdt.groovy.search.TypeLookupResult.TypeConfidence;
/**
* @author Andrew Eisenberg
* @created Nov 20, 2009 A simplified type lookup that targets the general case where a provider wants to add initialization to a
* class and add new methods/fields to certain types of objects
*/
public abstract class AbstractSimplifiedTypeLookup implements ITypeLookupExtension {
public static class TypeAndDeclaration {
public TypeAndDeclaration(ClassNode type, ASTNode declaration) {
this.type = type;
this.declaration = declaration;
this.declaringType = null;
this.extraDoc = null;
this.confidence = null;
}
public TypeAndDeclaration(ClassNode type, ASTNode declaration, ClassNode declaringType) {
this.type = type;
this.declaration = declaration;
this.declaringType = declaringType;
this.extraDoc = null;
this.confidence = null;
}
public TypeAndDeclaration(ClassNode type, ASTNode declaration, ClassNode declaringType, String extraDoc) {
this.type = type;
this.declaration = declaration;
this.declaringType = declaringType;
this.extraDoc = extraDoc;
this.confidence = null;
}
public TypeAndDeclaration(ClassNode type, ASTNode declaration, ClassNode declaringType, String extraDoc,
TypeConfidence confidence) {
this.type = type;
this.declaration = declaration;
this.declaringType = declaringType;
this.extraDoc = extraDoc;
this.confidence = confidence;
}
protected final ClassNode type;
protected final ClassNode declaringType;
protected final ASTNode declaration;
protected final String extraDoc;
protected final TypeConfidence confidence;
}
private boolean isStatic;
private Expression currentExpression;
/**
* @return true iff the current lookup is in a static scope
*/
protected boolean isStatic() {
return isStatic;
}
/**
* @return the expression AST node that is currently being inferred.
*/
protected Expression getCurrentExpression() {
return currentExpression;
}
/**
* @return true iff the current expression being inferred is a quoted string
*/
protected boolean isQuotedString() {
return currentExpression instanceof GStringExpression
|| currentExpression.getText().length() != currentExpression.getLength();
}
// not called, but must be implemented
public final TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNode objectExpressionType) {
return lookupType(node, scope, objectExpressionType, false);
}
public final TypeLookupResult lookupType(Expression node, VariableScope scope, ClassNode objectExpressionType,
boolean isStaticObjectExpression) {
ClassNode declaringType;
if (objectExpressionType != null) {
declaringType = objectExpressionType;
} else {
// Use delegate type if exists
declaringType = scope.getDelegateOrThis();
if (declaringType == null) {
declaringType = scope.getEnclosingTypeDeclaration();
if (declaringType == null) {
// part of an import statment
declaringType = VariableScope.OBJECT_CLASS_NODE;
}
}
}
// I would have likd to pass this value into lookupTypeAndDeclaration, but
// I can't break api here
isStatic = isStaticObjectExpression;
currentExpression = node;
TypeAndDeclaration tAndD = null;
if (node instanceof ConstantExpression || node instanceof GStringExpression || node instanceof VariableExpression) {
tAndD = lookupTypeAndDeclaration(declaringType, node.getText(), scope);
}
if (tAndD != null) {
TypeConfidence confidence = checkConfidence(node, tAndD.confidence, tAndD.declaration, tAndD.extraDoc);
return new TypeLookupResult(tAndD.type, tAndD.declaringType == null ? declaringType : tAndD.declaringType,
tAndD.declaration, confidence, scope, tAndD.extraDoc);
}
return null;
}
/**
* Gives an option for descendants to set confidence by their own
*/
protected TypeConfidence checkConfidence(Expression node, TypeConfidence originalConfidence, ASTNode declaration,
String extraDoc) {
return originalConfidence == null ? confidence() : originalConfidence;
}
/**
* @return the confidence level of lookup results for this type lookup. Defaults to {@link TypeConfidence#LOOSELY_INFERRED}
*/
protected TypeConfidence confidence() {
return TypeConfidence.LOOSELY_INFERRED;
}
public final TypeLookupResult lookupType(FieldNode node, VariableScope scope) {
return null;
}
public final TypeLookupResult lookupType(MethodNode node, VariableScope scope) {
return null;
}
public final TypeLookupResult lookupType(AnnotationNode node, VariableScope scope) {
return null;
}
public final TypeLookupResult lookupType(ImportNode node, VariableScope scope) {
return null;
}
public final TypeLookupResult lookupType(ClassNode node, VariableScope scope) {
return null;
}
public final TypeLookupResult lookupType(Parameter node, VariableScope scope) {
return null;
}
public void lookupInBlock(BlockStatement node, VariableScope scope) {
}
/**
* Clients should return a {@link TypeAndDeclaration} corresponding to an additional
*
* @param declaringType
* @param name
* @param scope
* @return the type and declaration corresponding to the name in the given declaring type. The declaration may be null, but this
* should be avoided in that it prevents the use of navigation and of javadoc hovers
*/
protected abstract TypeAndDeclaration lookupTypeAndDeclaration(ClassNode declaringType, String name, VariableScope scope);
}