From 05e57a6b153fd085e7dbf471f24a2aa63d3672eb Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 17 Mar 2011 10:07:42 +0300 Subject: [PATCH] safe cast resolve --- .../types/GrSafeCastExpressionImpl.java | 85 ++++++++++++++++++- .../lang/resolve/ResolveMethodTest.groovy | 4 + .../testdata/resolve/method/asType/A.groovy | 19 +++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 plugins/groovy/testdata/resolve/method/asType/A.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java index dde2ff576c54..9892900f8e30 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java @@ -17,19 +17,40 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.types; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiType; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.resolve.ResolveCache; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; /** * @author ven */ -public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafeCastExpression { +public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafeCastExpression, PsiPolyVariantReference { + + private static final class OurResolver implements ResolveCache.PolyVariantResolver { + @Override + public ResolveResult[] resolve(GrSafeCastExpressionImpl cast, boolean incompleteCode) { + return TypesUtil.getOverloadedOperatorCandidates( + cast.getOperand().getType(), + GroovyTokenTypes.kAS, + cast, + new PsiType[]{TypesUtil.createJavaLangClassType(cast.getCastTypeElement().getType(), cast.getProject(), cast.getResolveScope())} + ); + } + } + + private static final OurResolver OUR_RESOLVER = new OurResolver(); public GrSafeCastExpressionImpl(@NotNull ASTNode node) { super(node); @@ -56,4 +77,64 @@ public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafe public GrExpression getOperand() { return findChildByClass(GrExpression.class); } + + @Override + public PsiReference getReference() { + return this; + } + + @Override + public PsiElement getElement() { + return this; + } + + @Override + public TextRange getRangeInElement() { + final PsiElement as = findNotNullChildByType(GroovyTokenTypes.kAS); + final int offset = as.getStartOffsetInParent(); + return new TextRange(offset, offset + 2); + } + + @Override + public PsiElement resolve() { + return PsiImplUtil.extractUniqueResult(multiResolve(false)).getElement(); + } + + @NotNull + @Override + public String getCanonicalText() { + return getText(); + } + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + throw new UnsupportedOperationException("safe cast cannot be renamed"); + } + + @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + throw new UnsupportedOperationException("safe cast can be bounded to nothing"); + } + + @Override + public boolean isReferenceTo(PsiElement element) { + return getManager().areElementsEquivalent(resolve(), element); + } + + @NotNull + @Override + public Object[] getVariants() { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Override + public boolean isSoft() { + return false; + } + + @NotNull + @Override + public GroovyResolveResult[] multiResolve(boolean incompleteCode) { + return (GroovyResolveResult[])getManager().getResolveCache().resolveWithCaching(this, OUR_RESOLVER, false, incompleteCode); + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy index 1ba606c731d0..87ec00fe9302 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy @@ -644,4 +644,8 @@ class Zoo { public void testAvoidResolveLockInClosure() { assertNotNull resolve("A.groovy") } + + public void resoleAsType() { + assertInstanceOf resolve("A.groovy"), GrMethod + } } diff --git a/plugins/groovy/testdata/resolve/method/asType/A.groovy b/plugins/groovy/testdata/resolve/method/asType/A.groovy new file mode 100644 index 000000000000..3e85646e12e8 --- /dev/null +++ b/plugins/groovy/testdata/resolve/method/asType/A.groovy @@ -0,0 +1,19 @@ + +class C { + def bar = 5 + def box + + def asType(Class c) { + if (c == D) { + return new D() + } + } +} + +class D { + def D(C c) {} +} + + + +print(new C() as D) \ No newline at end of file