Changed API in ResolutionFacade to resolve to element to support 3 modes

This commit is contained in:
Valentin Kipyatkov
2014-12-07 05:39:27 -07:00
parent 9c8b7ed6f5
commit 2a41856af6
17 changed files with 82 additions and 48 deletions
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.lazy
public enum class BodyResolveMode {
FULL
PARTIAL
PARTIAL_FOR_COMPLETION
}
@@ -59,12 +59,12 @@ public abstract class ElementResolver {
@NotNull
public BindingContext getElementAdditionalResolve(@NotNull JetElement jetElement) {
return elementAdditionalResolve(jetElement, PartialBodyResolveProvider.NONE);
return elementAdditionalResolve(jetElement, jetElement, BodyResolveMode.FULL);
}
@NotNull
public BindingContext resolveToElement(@NotNull JetElement jetElement) {
return resolveToElement(jetElement, false);
return resolveToElement(jetElement, BodyResolveMode.FULL);
}
@NotNull
@@ -73,7 +73,7 @@ public abstract class ElementResolver {
}
@NotNull
public BindingContext resolveToElement(@NotNull JetElement jetElement, boolean partialBodyResolve) {
public BindingContext resolveToElement(@NotNull JetElement jetElement, BodyResolveMode bodyResolveMode) {
@SuppressWarnings("unchecked") JetElement elementOfAdditionalResolve = (JetElement) JetPsiUtil.getTopmostParentOfTypes(
jetElement,
JetNamedFunction.class,
@@ -93,12 +93,9 @@ public abstract class ElementResolver {
elementOfAdditionalResolve = jetElement;
}
if (partialBodyResolve && elementOfAdditionalResolve instanceof JetDeclaration) {
if (bodyResolveMode != BodyResolveMode.FULL) {
//TODO: do not resolve with filter if whole body resolve cached already
PartialBodyResolveFilter filter = new PartialBodyResolveFilter(
jetElement,
(JetDeclaration) elementOfAdditionalResolve, probablyNothingCallableNames());
return elementAdditionalResolve(elementOfAdditionalResolve, filter);
return elementAdditionalResolve(elementOfAdditionalResolve, jetElement, bodyResolveMode);
}
return getElementAdditionalResolve(elementOfAdditionalResolve);
@@ -127,7 +124,8 @@ public abstract class ElementResolver {
@NotNull
protected BindingContext elementAdditionalResolve(
@NotNull JetElement resolveElement,
@NotNull PartialBodyResolveProvider partialResolveProvider
@NotNull JetElement contextElement,
@NotNull BodyResolveMode bodyResolveMode
) {
// All additional resolve should be done to separate trace
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(
@@ -135,6 +133,18 @@ public abstract class ElementResolver {
JetFile file = resolveElement.getContainingJetFile();
PartialBodyResolveProvider partialResolveProvider;
if (bodyResolveMode != BodyResolveMode.FULL && resolveElement instanceof JetDeclaration) {
partialResolveProvider = new PartialBodyResolveFilter(
contextElement,
(JetDeclaration) resolveElement,
probablyNothingCallableNames(),
bodyResolveMode == BodyResolveMode.PARTIAL_FOR_COMPLETION);
}
else {
partialResolveProvider = PartialBodyResolveProvider.NONE;
}
if (resolveElement instanceof JetNamedFunction) {
functionAdditionalResolve(resolveSession, (JetNamedFunction) resolveElement, trace, file, partialResolveProvider);
}
@@ -165,7 +175,7 @@ public abstract class ElementResolver {
typeConstraintAdditionalResolve(resolveSession, (JetTypeConstraint) resolveElement);
}
else if (resolveElement instanceof JetCodeFragment) {
codeFragmentAdditionalResolve(resolveSession, (JetCodeFragment) resolveElement, trace);
codeFragmentAdditionalResolve(resolveSession, (JetCodeFragment) resolveElement, trace, bodyResolveMode);
}
else if (PsiTreeUtil.getParentOfType(resolveElement, JetPackageDirective.class) != null) {
packageRefAdditionalResolve(resolveSession, trace, resolveElement);
@@ -218,7 +228,8 @@ public abstract class ElementResolver {
private void codeFragmentAdditionalResolve(
ResolveSession resolveSession,
JetCodeFragment codeFragment,
BindingTrace trace
BindingTrace trace,
BodyResolveMode bodyResolveMode
) {
JetElement codeFragmentExpression = codeFragment.getContentElement();
if (!(codeFragmentExpression instanceof JetExpression)) return;
@@ -238,7 +249,7 @@ public abstract class ElementResolver {
if (!(contextElement instanceof JetExpression)) return;
JetExpression contextExpression = (JetExpression) contextElement;
BindingContext contextForElement = resolveToElement((JetElement) contextElement, true);
BindingContext contextForElement = resolveToElement((JetElement) contextElement, bodyResolveMode);
scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
dataFlowInfoForContextElement = getDataFlowInfo(contextForElement, contextExpression);
@@ -35,7 +35,8 @@ import org.jetbrains.jet.lang.psi.psiUtil.isProbablyNothing
class PartialBodyResolveFilter(
elementToResolve: JetElement,
private val declaration: JetDeclaration,
probablyNothingCallableNames: ProbablyNothingCallableNames
probablyNothingCallableNames: ProbablyNothingCallableNames,
forCompletion: Boolean
) : PartialBodyResolveProvider() {
private val statementMarks = StatementMarks()
@@ -74,7 +75,7 @@ class PartialBodyResolveFilter(
}
})
statementMarks.mark(elementToResolve, MarkLevel.NEED_COMPLETION)
statementMarks.mark(elementToResolve, if (forCompletion) MarkLevel.NEED_COMPLETION else MarkLevel.NEED_REFERENCE_RESOLVE)
declaration.blocks().forEach { processBlock(it) }
}
@@ -35,14 +35,15 @@ import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode;
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.plugin.decompiler.navigation.JetSourceNavigationHelper;
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
import org.jetbrains.jet.plugin.stubindex.JetTopLevelClassByPackageIndex;
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetTopLevelClassByPackageIndex;
import org.jetbrains.jet.plugin.stubindex.PackageIndexUtil;
import java.util.*;
@@ -84,7 +85,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
KotlinCacheService.OBJECT$.getInstance(classOrObject.getProject()).getLazyResolveSession(classOrObject);
if (classOrObject.isLocal()) {
BindingContext bindingContext = session.resolveToElement(classOrObject);
BindingContext bindingContext = session.resolveToElement(classOrObject, BodyResolveMode.FULL);
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject);
if (descriptor == null) {
@@ -38,6 +38,7 @@ import org.jetbrains.jet.plugin.util.ProjectRootsUtil
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
private val LOG = Logger.getInstance(javaClass<KotlinCacheService>())
@@ -49,12 +50,8 @@ public class KotlinCacheService(val project: Project) {
public fun getResolutionFacade(elements: List<JetElement>): ResolutionFacade {
val cache = getCacheToAnalyzeFiles(elements.map { it.getContainingJetFile() })
return object : ResolutionFacade {
override fun analyze(element: JetElement): BindingContext {
return cache.getLazyResolveSession(element).resolveToElement(element)
}
override fun analyzeWithPartialBodyResolve(element: JetElement): BindingContext {
return cache.getLazyResolveSession(element).resolveToElementWithPartialBodyResolve(element)
override fun analyze(element: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
return cache.getLazyResolveSession(element).resolveToElement(element, bodyResolveMode)
}
override fun findModuleDescriptor(element: JetElement): ModuleDescriptor {
@@ -65,6 +65,7 @@ import org.jetbrains.jet.plugin.project.TargetPlatformDetector
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public trait CacheExtension<T> {
public val platform: TargetPlatform
@@ -292,7 +293,7 @@ private object KotlinResolveDataProvider {
else {
if (contextElement !is JetExpression) return BindingContext.EMPTY
val contextForElement = contextElement.getResolutionFacade().analyzeWithPartialBodyResolve(contextElement)
val contextForElement = contextElement.getResolutionFacade().analyze(contextElement, BodyResolveMode.PARTIAL_FOR_COMPLETION) //TODO: discuss it
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, contextElement]
dataFlowInfo = contextForElement.getDataFlowInfo(contextElement)
@@ -22,12 +22,11 @@ import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.analyzer.AnalysisResult
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public trait ResolutionFacade {
public fun analyze(element: JetElement): BindingContext
public fun analyzeWithPartialBodyResolve(element: JetElement): BindingContext
public fun analyze(element: JetElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext
public fun analyzeFullyAndGetResult(elements: Collection<JetElement>): AnalysisResult
@@ -28,11 +28,7 @@ import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.PartialBodyResolveProvider;
import org.jetbrains.jet.lang.resolve.lazy.DefaultNothingCallableNames;
import org.jetbrains.jet.lang.resolve.lazy.ElementResolver;
import org.jetbrains.jet.lang.resolve.lazy.ProbablyNothingCallableNames;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.*;
import org.jetbrains.jet.plugin.stubindex.JetProbablyNothingFunctionShortNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetProbablyNothingPropertyShortNameIndex;
import org.jetbrains.jet.storage.LazyResolveStorageManager;
@@ -62,7 +58,7 @@ public class ResolveElementCache extends ElementResolver {
manager.createWeaklyRetainedMemoizedFunction(new Function1<JetElement, BindingContext>() {
@Override
public BindingContext invoke(JetElement jetElement) {
return elementAdditionalResolve(jetElement, PartialBodyResolveProvider.NONE);
return elementAdditionalResolve(jetElement, jetElement, BodyResolveMode.FULL);
}
});
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode;
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
@@ -50,12 +51,8 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer {
}
@NotNull
public BindingContext resolveToElement(JetElement element) {
return resolveElementCache.resolveToElement(element, false);
}
public BindingContext resolveToElementWithPartialBodyResolve(JetElement element) {
return resolveElementCache.resolveToElement(element, true);
public BindingContext resolveToElement(JetElement element, BodyResolveMode bodyResolveMode) {
return resolveElementCache.resolveToElement(element, bodyResolveMode);
}
@NotNull
@@ -53,6 +53,7 @@ import org.jetbrains.jet.lang.psi.JetContainerNode
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.psi.psiUtil.siblings
import org.jetbrains.jet.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public class CheckPartialBodyResolveAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
@@ -74,7 +75,7 @@ public class CheckPartialBodyResolveAction : AnAction() {
progressIndicator?.setText2(file.getVirtualFile().getPath())
val partialResolveDump = dumpResolve(file) {(element, resolutionFacade) ->
resolutionFacade.analyzeWithPartialBodyResolve(element)
resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
}
val goldDump = dumpResolve(file) {(element, resolutionFacade) ->
resolutionFacade.analyze(element)
@@ -43,6 +43,7 @@ import org.jetbrains.jet.plugin.util.makeNotNullable
import org.jetbrains.jet.plugin.util.CallType
import org.jetbrains.jet.plugin.completion.isVisible
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindExclude
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
class CompletionSessionConfiguration(
val completeNonImportedDeclarations: Boolean,
@@ -60,7 +61,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
private val file = position.getContainingFile() as JetFile
protected val resolutionFacade: ResolutionFacade = file.getResolutionFacade()
protected val moduleDescriptor: ModuleDescriptor = resolutionFacade.findModuleDescriptor(file)
protected val bindingContext: BindingContext? = jetReference?.let { resolutionFacade.analyzeWithPartialBodyResolve(it.expression) }
protected val bindingContext: BindingContext? = jetReference?.let { resolutionFacade.analyze(it.expression, BodyResolveMode.PARTIAL_FOR_COMPLETION) }
protected val inDescriptor: DeclarationDescriptor? = jetReference?.let { bindingContext!!.get(BindingContext.RESOLUTION_SCOPE, it.expression)?.getContainingDeclaration() }
// set prefix matcher here to override default one which relies on CompletionUtil.findReferencePrefix()
@@ -58,6 +58,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.plugin.caches.resolve.getResolutionFacade
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public class KotlinCompletionContributor : CompletionContributor() {
@@ -285,7 +286,7 @@ public class KotlinCompletionContributor : CompletionContributor() {
assert(balance > 0)
val nameRef = nameToken.getParent() as? JetNameReferenceExpression ?: return null
val bindingContext = nameRef.getResolutionFacade().analyzeWithPartialBodyResolve(nameRef) //TODO: analyze with "resolve" mode instead of "completion"
val bindingContext = nameRef.getResolutionFacade().analyze(nameRef, BodyResolveMode.PARTIAL)
val target = bindingContext[BindingContext.REFERENCE_TARGET, nameRef]
val targets = if (target != null) {
listOf(target)
@@ -40,6 +40,7 @@ import org.jetbrains.jet.plugin.caches.resolve.getResolutionFacade
import org.jetbrains.jet.plugin.util.application.runWriteAction
import org.jetbrains.jet.plugin.refactoring.EmptyValidator
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange, lambdaType: JetType) {
val explicitParameterTypes = needExplicitParameterTypes(context, placeholderRange, lambdaType)
@@ -84,7 +85,7 @@ private fun needExplicitParameterTypes(context: InsertionContext, placeholderRan
if (expression == null) return false
val resolutionFacade = file.getResolutionFacade()
val bindingContext = resolutionFacade.analyzeWithPartialBodyResolve(expression)
val bindingContext = resolutionFacade.analyze(expression, BodyResolveMode.PARTIAL)
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade).calculate(expression) ?: return false
val functionTypes = expectedInfos.map { it.type }.filter { KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it) }.toSet()
if (functionTypes.size <= 1) return false
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.psi.JetNameReferenceExpression
import org.jetbrains.jet.plugin.caches.resolve.getResolutionFacade
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public object KotlinClassInsertHandler : BaseDeclarationInsertHandler() {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
@@ -49,7 +50,7 @@ public object KotlinClassInsertHandler : BaseDeclarationInsertHandler() {
val token = file.findElementAt(startOffset)
val nameRef = token.getParent() as? JetNameReferenceExpression
if (nameRef != null) {
val bindingContext = nameRef.getResolutionFacade().analyzeWithPartialBodyResolve(nameRef)
val bindingContext = nameRef.getResolutionFacade().analyze(nameRef, BodyResolveMode.PARTIAL)
val target = bindingContext[BindingContext.REFERENCE_TARGET, nameRef] as? ClassDescriptor
if (target != null && DescriptorUtils.getFqNameSafe(target).asString() == qualifiedName) return
}
@@ -39,6 +39,7 @@ import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.JetVisibilityChecker;
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindExclude;
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter;
@@ -239,7 +240,7 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith
StringBuilder builder = new StringBuilder();
PsiElement owner = context.getParameterOwner();
BindingContext bindingContext = resolutionFacade.analyze((JetElement) owner);
BindingContext bindingContext = resolutionFacade.analyze((JetElement) owner, BodyResolveMode.FULL);
for (int i = 0; i < valueParameters.size(); ++i) {
if (i != 0) {
@@ -383,7 +384,7 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith
}
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(callNameExpression.getContainingJetFile());
BindingContext bindingContext = resolutionFacade.analyze(callNameExpression);
BindingContext bindingContext = resolutionFacade.analyze(callNameExpression, BodyResolveMode.FULL);
JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, callNameExpression);
final DeclarationDescriptor placeDescriptor;
@@ -55,6 +55,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
@@ -303,7 +304,7 @@ public class KotlinInlineValHandler extends InlineActionHandler {
@NotNull ResolutionFacade resolutionFacade
) {
JetFunctionLiteral functionLiteral = functionLiteralExpression.getFunctionLiteral();
BindingContext context = resolutionFacade.analyze(functionLiteralExpression);
BindingContext context = resolutionFacade.analyze(functionLiteralExpression, BodyResolveMode.FULL);
for (Diagnostic diagnostic : context.getDiagnostics()) {
DiagnosticFactory<?> factory = diagnostic.getFactory();
PsiElement element = diagnostic.getPsiElement();
@@ -323,7 +324,7 @@ public class KotlinInlineValHandler extends InlineActionHandler {
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(containingFile);
for (JetExpression inlinedExpression : inlinedExpressions) {
BindingContext context = resolutionFacade.analyze(inlinedExpression);
BindingContext context = resolutionFacade.analyze(inlinedExpression, BodyResolveMode.FULL);
Call call = CallUtilPackage.getCallWithAssert(inlinedExpression, context);
JetElement callElement = call.getCallElement();
@@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.psi.JetPsiFactory
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.psi.JetReferenceExpression
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
import org.jetbrains.jet.lang.resolve.lazy.BodyResolveMode
public abstract class AbstractPartialBodyResolveTest : JetLightCodeInsightFixtureTestCase() {
override fun getTestDataPath() = JetTestCaseBuilder.getHomeDirectory()
@@ -65,7 +66,7 @@ public abstract class AbstractPartialBodyResolveTest : JetLightCodeInsightFixtur
val resolutionFacade = file.getResolutionFacade()
// optimized resolve
val (target1, type1, processedStatements1) = doResolve(expression, resolutionFacade.analyzeWithPartialBodyResolve(expression))
val (target1, type1, processedStatements1) = doResolve(expression, resolutionFacade.analyze(expression, BodyResolveMode.PARTIAL_FOR_COMPLETION))
// full body resolve
val (target2, type2, processedStatements2) = doResolve(expression, resolutionFacade.analyze(expression))