/*******************************************************************************
* Copyright (c) 2011 Codehaus.org, SpringSource, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Eisenberg - Initial implemenation
*******************************************************************************/
package org.codehaus.groovy.eclipse.dsl.contributions;
import groovyjarjarasm.asm.Opcodes;
import java.util.List;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.PropertyNode;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.eclipse.codeassist.ProposalUtils;
import org.codehaus.groovy.eclipse.codeassist.proposals.GroovyPropertyProposal;
import org.codehaus.groovy.eclipse.codeassist.proposals.IGroovyProposal;
import org.codehaus.groovy.eclipse.dsl.lookup.ResolverCache;
import org.eclipse.jdt.groovy.search.AbstractSimplifiedTypeLookup.TypeAndDeclaration;
/**
*
* @author andrew
* @created Nov 17, 2010
*/
public class PropertyContributionElement implements IContributionElement {
private static final ClassNode UNKNOWN_TYPE = ClassHelper.DYNAMIC_TYPE;
private final String propName;
private final String propType;
private final String declaringType;
private final boolean isStatic;
private ClassNode cachedDeclaringType;
private ClassNode cachedType;
private final String provider;
private final String doc;
private final int relevanceMultiplier;
private final boolean isDeprecated;
public PropertyContributionElement(String propName, String propType, String declaringType, boolean isStatic, String provider, String doc, boolean isDeprecated, int relevanceMultiplier) {
super();
this.propName = propName;
this.propType = propType;
this.isStatic = isStatic;
this.declaringType = declaringType;
this.isDeprecated = isDeprecated;
this.relevanceMultiplier = relevanceMultiplier;
this.provider = provider == null ? GROOVY_DSL_PROVIDER : provider;
this.doc = doc == null ? NO_DOC + this.provider : doc;
}
public IGroovyProposal toProposal(ClassNode declaringType, ResolverCache resolver) {
GroovyPropertyProposal groovyPropertyProposal = new GroovyPropertyProposal(toProperty(declaringType, resolver), provider);
groovyPropertyProposal.setRelevanceMultiplier(relevanceMultiplier);
return groovyPropertyProposal;
}
public TypeAndDeclaration lookupType(String name, ClassNode declaringType, ResolverCache resolver) {
return name.equals(propName) ? new TypeAndDeclaration(ensureReturnType(resolver), toProperty(declaringType, resolver),
ensureDeclaringType(declaringType, resolver), doc) : null;
}
private PropertyNode toProperty(ClassNode declaringType, ResolverCache resolver) {
ClassNode realDeclaringType = ensureDeclaringType(declaringType, resolver);
PropertyNode prop = new PropertyNode(new FieldNode(propName, opcode(), ensureReturnType(resolver),
realDeclaringType, null), opcode(), null, null);
prop.setDeclaringClass(realDeclaringType);
prop.getField().setDeclaringClass(realDeclaringType);
return prop;
}
protected int opcode() {
int modifiers = isStatic ? Opcodes.ACC_STATIC : Opcodes.ACC_PUBLIC;
modifiers |= isDeprecated ? Opcodes.ACC_DEPRECATED : 0;
return modifiers;
}
protected ClassNode ensureReturnType(ResolverCache resolver) {
if (cachedType == null) {
cachedType = resolver.resolve(propType);
}
return cachedType == null ? UNKNOWN_TYPE : cachedType;
}
protected ClassNode ensureDeclaringType(ClassNode lexicalDeclaringType, ResolverCache resolver) {
if (declaringType != null && cachedDeclaringType == null) {
cachedDeclaringType = resolver.resolve(declaringType);
}
return cachedDeclaringType == null ? lexicalDeclaringType : cachedDeclaringType;
}
public String contributionName() {
return propName;
}
public String description() {
return "Property: " + declaringType + "." + propName;
}
public String getDeclaringTypeName() {
return declaringType;
}
@Override
public String toString() {
return "public " + (isStatic ? "static " : "") + (isDeprecated ? "deprecated " : "")
+ propType + " " + declaringType + "." + propName + " (" + provider + ")";
}
public List<IGroovyProposal> extraProposals(ClassNode declaringType, ResolverCache resolver, Expression enclosingExpression) {
return ProposalUtils.NO_PROPOSALS;
}
}