/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.impl.expressions;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiType;
import gw.lang.parser.IExpansionPropertyInfo;
import gw.lang.parser.expressions.IFeatureLiteralExpression;
import gw.lang.reflect.IConstructorInfo;
import gw.lang.reflect.IFeatureInfo;
import gw.lang.reflect.IHasParameterInfos;
import gw.lang.reflect.IMethodInfo;
import gw.lang.reflect.IMethodInfoDelegate;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IPropertyInfoDelegate;
import gw.plugin.ij.lang.GosuTokenTypes;
import gw.plugin.ij.lang.parser.GosuCompositeElement;
import gw.plugin.ij.lang.psi.api.types.IGosuCodeReferenceElement;
import gw.plugin.ij.lang.psi.api.types.IGosuTypeElement;
import gw.plugin.ij.lang.psi.api.types.IGosuTypeParameterList;
import gw.plugin.ij.lang.psi.impl.GosuElementVisitor;
import gw.plugin.ij.lang.psi.impl.resolvers.PsiFeatureResolver;
import gw.plugin.ij.util.ExecutionUtil;
import gw.plugin.ij.util.SafeCallable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GosuFeatureLiteralExpressionImpl extends GosuReferenceExpressionImpl<IFeatureLiteralExpression> implements IGosuCodeReferenceElement, IGosuTypeElement {
public GosuFeatureLiteralExpressionImpl(GosuCompositeElement node) {
super(node);
}
@Nullable
public PsiElement getReferenceNameElement() {
return findLastChildByType(GosuTokenTypes.TT_IDENTIFIER);
}
@Override
public IGosuCodeReferenceElement getQualifier() {
final PsiElement firstChild = getFirstChild();
return firstChild instanceof IGosuCodeReferenceElement ? (IGosuCodeReferenceElement) firstChild : null;
}
@Override
public void setQualifier(IGosuCodeReferenceElement newQualifier) {
throw new UnsupportedOperationException("Men at work");
}
@Nullable
public IGosuTypeParameterList getTypeParameterList() {
return null;
}
@Override
public PsiType[] getTypeArguments() {
return PsiType.EMPTY_ARRAY;
}
@Override
public PsiElement resolve() {
return ExecutionUtil.execute(new SafeCallable<PsiElement>(this) {
public PsiElement execute() throws Exception {
IFeatureInfo feature = getParsedElement().getFeature();
if (feature == null) {
return null;
} else if (feature instanceof IPropertyInfo) {
return PsiFeatureResolver.resolveProperty((IPropertyInfo) getRootFeatureInfo(feature), GosuFeatureLiteralExpressionImpl.this);
} else if (feature instanceof IMethodInfo || feature instanceof IConstructorInfo) {
return PsiFeatureResolver.resolveMethodOrConstructor((IHasParameterInfos) getRootFeatureInfo(feature), GosuFeatureLiteralExpressionImpl.this);
}
throw new AssertionError();
}
});
}
@Nullable
private IFeatureInfo getRootFeatureInfo(IFeatureInfo feature) {
try {
while (feature instanceof IPropertyInfoDelegate) {
feature = ((IPropertyInfoDelegate) feature).getSource();
}
while (feature instanceof IExpansionPropertyInfo) {
feature = ((IExpansionPropertyInfo) feature).getDelegate();
}
while (feature instanceof IMethodInfoDelegate) {
feature = ((IMethodInfoDelegate) feature).getSource();
}
return feature;
} catch (Exception e) {
return null; // No property exists, pe is errant
}
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if( visitor instanceof GosuElementVisitor) {
((GosuElementVisitor)visitor).visitFeatureLiteralExpression(this);
}
else {
visitor.visitElement( this );
}
}
}