Fixed partial body resolve when element to resolve is not inside body

This commit is contained in:
Valentin Kipyatkov
2014-11-18 16:26:14 +03:00
parent f56d89c487
commit 78e26c0cf9
3 changed files with 29 additions and 13 deletions
@@ -91,9 +91,21 @@ public abstract class ElementResolver {
} }
if (partialBodyResolve && elementOfAdditionalResolve instanceof JetDeclarationWithBody) { if (partialBodyResolve && elementOfAdditionalResolve instanceof JetDeclarationWithBody) {
//TODO: do not resolve again if whole body resolve cached already
JetExpression body = ((JetDeclarationWithBody) elementOfAdditionalResolve).getBodyExpression(); JetExpression body = ((JetDeclarationWithBody) elementOfAdditionalResolve).getBodyExpression();
Function1<JetElement, Boolean> filter = body != null ? new PartialBodyResolveFilter(jetElement, body) : null; //TODO: do not resolve with filter if whole body resolve cached already
boolean inBody = body != null && PsiTreeUtil.isAncestor(body, jetElement, false);
Function1<JetElement, Boolean> filter;
if (inBody) {
filter = new PartialBodyResolveFilter(jetElement, body);
}
else { // do as less as possible body-resolve
filter = new Function1<JetElement, Boolean>() {
@Override
public Boolean invoke(JetElement element) {
return false;
}
};
}
return elementAdditionalResolve(elementOfAdditionalResolve, filter); return elementAdditionalResolve(elementOfAdditionalResolve, filter);
} }
@@ -121,7 +133,10 @@ public abstract class ElementResolver {
} }
@NotNull @NotNull
protected BindingContext elementAdditionalResolve(@NotNull JetElement resolveElement, @Nullable Function1<JetElement, Boolean> filter) { protected BindingContext elementAdditionalResolve(
@NotNull JetElement resolveElement,
@Nullable Function1<JetElement, Boolean> bodyResolveFilter
) {
// All additional resolve should be done to separate trace // All additional resolve should be done to separate trace
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace( BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(
new DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement)); new DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement));
@@ -129,10 +144,10 @@ public abstract class ElementResolver {
JetFile file = resolveElement.getContainingJetFile(); JetFile file = resolveElement.getContainingJetFile();
if (resolveElement instanceof JetNamedFunction) { if (resolveElement instanceof JetNamedFunction) {
functionAdditionalResolve(resolveSession, (JetNamedFunction) resolveElement, trace, file, filter); functionAdditionalResolve(resolveSession, (JetNamedFunction) resolveElement, trace, file, bodyResolveFilter);
} }
else if (resolveElement instanceof JetClassInitializer) { else if (resolveElement instanceof JetClassInitializer) {
initializerAdditionalResolve(resolveSession, (JetClassInitializer) resolveElement, trace, file, filter); initializerAdditionalResolve(resolveSession, (JetClassInitializer) resolveElement, trace, file, bodyResolveFilter);
} }
else if (resolveElement instanceof JetProperty) { else if (resolveElement instanceof JetProperty) {
propertyAdditionalResolve(resolveSession, (JetProperty) resolveElement, trace, file); propertyAdditionalResolve(resolveSession, (JetProperty) resolveElement, trace, file);
@@ -149,7 +164,7 @@ public abstract class ElementResolver {
annotationAdditionalResolve(resolveSession, (JetAnnotationEntry) resolveElement); annotationAdditionalResolve(resolveSession, (JetAnnotationEntry) resolveElement);
} }
else if (resolveElement instanceof JetClass) { else if (resolveElement instanceof JetClass) {
constructorAdditionalResolve(resolveSession, (JetClass) resolveElement, trace, file, filter); constructorAdditionalResolve(resolveSession, (JetClass) resolveElement, trace, file, bodyResolveFilter);
} }
else if (resolveElement instanceof JetTypeParameter) { else if (resolveElement instanceof JetTypeParameter) {
typeParameterAdditionalResolve(resolveSession, (JetTypeParameter) resolveElement); typeParameterAdditionalResolve(resolveSession, (JetTypeParameter) resolveElement);
@@ -353,13 +368,13 @@ public abstract class ElementResolver {
JetNamedFunction namedFunction, JetNamedFunction namedFunction,
BindingTrace trace, BindingTrace trace,
JetFile file, JetFile file,
@Nullable Function1<JetElement, Boolean> filter @Nullable Function1<JetElement, Boolean> bodyResolveFilter
) { ) {
JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(namedFunction); JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(namedFunction);
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction); FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
ForceResolveUtil.forceResolveAllContents(functionDescriptor); ForceResolveUtil.forceResolveAllContents(functionDescriptor);
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file, filter); BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file, bodyResolveFilter);
bodyResolver.resolveFunctionBody(createEmptyContext(resolveSession), trace, namedFunction, functionDescriptor, scope); bodyResolver.resolveFunctionBody(createEmptyContext(resolveSession), trace, namedFunction, functionDescriptor, scope);
} }
@@ -384,7 +399,7 @@ public abstract class ElementResolver {
constructorDescriptor, scope); constructorDescriptor, scope);
} }
private boolean initializerAdditionalResolve( private void initializerAdditionalResolve(
ResolveSession resolveSession, ResolveSession resolveSession,
JetClassInitializer classInitializer, JetClassInitializer classInitializer,
BindingTrace trace, BindingTrace trace,
@@ -396,8 +411,6 @@ public abstract class ElementResolver {
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file, filter); BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file, filter);
bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor); bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor);
return true;
} }
private BodyResolver createBodyResolver(ResolveSession resolveSession, BindingTrace trace, JetFile file, @Nullable Function1<JetElement, Boolean> filter) { private BodyResolver createBodyResolver(ResolveSession resolveSession, BindingTrace trace, JetFile file, @Nullable Function1<JetElement, Boolean> filter) {
@@ -25,6 +25,7 @@ import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.jet.JetNodeTypes import org.jetbrains.jet.JetNodeTypes
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: JetExpression) : (JetElement) -> Boolean { class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: JetExpression) : (JetElement) -> Boolean {
@@ -32,6 +33,8 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J
private val processedBlocks = HashSet<JetBlockExpression>() private val processedBlocks = HashSet<JetBlockExpression>()
;{ ;{
assert(body.isAncestor(elementToResolve, strict = false))
addStatementsToResolve(elementToResolve) addStatementsToResolve(elementToResolve)
} }
@@ -45,7 +48,8 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J
private fun addStatementsToResolve(element: JetElement) { private fun addStatementsToResolve(element: JetElement) {
if (element == body) return if (element == body) return
val parent = element.getParent() as JetElement val parent = element.getParent() as? JetElement
?: return
if (parent is JetBlockExpression) { if (parent is JetBlockExpression) {
processBlock(parent) processBlock(parent)
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider; import org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider;
import org.jetbrains.jet.lang.resolve.lazy.ElementResolver; import org.jetbrains.jet.lang.resolve.lazy.ElementResolver;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.storage.LazyResolveStorageManager; import org.jetbrains.jet.storage.LazyResolveStorageManager;