/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.lang.psi.impl.expressions; import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl; import com.intellij.psi.JavaElementVisitor; import com.intellij.psi.JavaResolveResult; import com.intellij.psi.PsiCallExpression; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiExpressionList; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReferenceParameterList; import com.intellij.psi.PsiType; import gw.lang.parser.IConstructorFunctionSymbol; import gw.lang.parser.IDynamicFunctionSymbol; import gw.lang.parser.IFunctionSymbol; import gw.lang.parser.IReducedDynamicFunctionSymbol; import gw.lang.parser.expressions.IMethodCallExpression; import gw.lang.reflect.IAttributedFeatureInfo; import gw.lang.reflect.IFunctionType; import gw.lang.reflect.IHasParameterInfos; import gw.lang.reflect.gs.IGosuMethodInfo; import gw.plugin.ij.lang.GosuTokenImpl; import gw.plugin.ij.lang.GosuTokenTypes; import gw.plugin.ij.lang.parser.GosuCompositeElement; import gw.plugin.ij.lang.parser.GosuElementTypes; 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 GosuMethodCallExpressionImpl extends GosuReferenceExpressionImpl<IMethodCallExpression> implements IGosuCodeReferenceElement, IGosuTypeElement, PsiCallExpression { public GosuMethodCallExpressionImpl(GosuCompositeElement node) { super(node); } @Nullable public PsiElement getReferenceNameElement() { PsiElement child = findLastChildByType( GosuTokenTypes.TT_IDENTIFIER ); if( child == null ) { // Could be a non-reserved keyword child = getFirstChild(); if( child instanceof GosuTokenImpl ) { return child; } } return child; } @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; } @NotNull @Override public PsiReferenceParameterList getTypeArgumentList() { return null; } @Override public PsiType[] getTypeArguments() { return PsiType.EMPTY_ARRAY; } @Override public PsiElement resolve() { return ExecutionUtil.execute(new SafeCallable<PsiElement>(this) { @Nullable public PsiElement execute() throws Exception { final IMethodCallExpression parsedElement = getParsedElement(); if (parsedElement == null) { return null; } IHasParameterInfos featureInfo = null; final IFunctionType functionType = parsedElement.getFunctionType(); if (functionType != null) { featureInfo = (IHasParameterInfos) functionType.getMethodOrConstructorInfo(); } final IFunctionSymbol functionSymbol = parsedElement.getFunctionSymbol(); if (featureInfo == null) { if (functionSymbol instanceof IConstructorFunctionSymbol) { featureInfo = ((IConstructorFunctionSymbol) functionSymbol).getConstructorInfo(); } else if (functionSymbol instanceof IDynamicFunctionSymbol) { featureInfo = (IHasParameterInfos) ((IDynamicFunctionSymbol) functionSymbol).getMethodOrConstructorInfo(true); } } if (featureInfo != null) { final IHasParameterInfos info = resolveParamerizedFeatureInfo(featureInfo); return PsiFeatureResolver.resolveMethodOrConstructor(info, GosuMethodCallExpressionImpl.this); } else { return functionSymbol != null ? PsiFeatureResolver.resolveMethodOrConstructor(functionSymbol, GosuMethodCallExpressionImpl.this) : null; } } }); } @NotNull private IHasParameterInfos resolveParamerizedFeatureInfo(@NotNull IHasParameterInfos featureInfo) { if (featureInfo.getOwnersType().isParameterizedType() && featureInfo instanceof IGosuMethodInfo) { final IReducedDynamicFunctionSymbol dfs = ((IGosuMethodInfo) featureInfo).getDfs(); if (dfs != null) { final IReducedDynamicFunctionSymbol backingDfs = dfs.getBackingDfs(); if (backingDfs != null) { final IAttributedFeatureInfo resolvedFeatureInfo = backingDfs.getMethodOrConstructorInfo(); if (resolvedFeatureInfo instanceof IHasParameterInfos) { featureInfo = (IHasParameterInfos) resolvedFeatureInfo; } } } } return featureInfo; } @Override public void accept( @NotNull PsiElementVisitor visitor ) { if( visitor instanceof JavaElementVisitor && !(visitor instanceof HighlightVisitorImpl) ) { ((JavaElementVisitor)visitor).visitCallExpression(this); } else if( visitor instanceof GosuElementVisitor) { ((GosuElementVisitor)visitor).visitMethodCallExpression(this); } else { visitor.visitElement( this ); } } @NotNull @Override public PsiExpressionList getArgumentList() { return (GosuExpressionListImpl)findChildByType( GosuElementTypes.ELEM_TYPE_ArgumentListClause ); } @Override public PsiMethod resolveMethod() { PsiElement ref = resolve(); return ref instanceof PsiMethod ? (PsiMethod)ref : null; } @NotNull @Override public JavaResolveResult resolveMethodGenerics() { throw new UnsupportedOperationException( "Not implemented yet" ); } }