Provide overloads with explicit resolutionFacade for resolutionApi
To ensure stable results of subsequent resolution api method calls, it is require to provide same resolution facade, as getResolutionFacade function doesn't guarantee to have same result in subsequent calls due to soft caching
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
||||
|
||||
/**
|
||||
* This function throws exception when resolveToDescriptorIfAny returns null, otherwise works equivalently.
|
||||
*/
|
||||
fun KtDeclaration.unsafeResolveToDescriptor(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL
|
||||
): DeclarationDescriptor =
|
||||
resolveToDescriptorIfAny(resolutionFacade, bodyResolveMode) ?: throw NoDescriptorForDeclarationException(this)
|
||||
|
||||
|
||||
/**
|
||||
* This function first uses declaration resolvers to resolve this declaration and/or additional declarations (e.g. its parent),
|
||||
* and then takes the relevant descriptor from binding context.
|
||||
* The exact set of declarations to resolve depends on bodyResolveMode
|
||||
*/
|
||||
fun KtDeclaration.resolveToDescriptorIfAny(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): DeclarationDescriptor? {
|
||||
//TODO: BodyResolveMode.PARTIAL is not quite safe!
|
||||
val context = analyze(resolutionFacade, bodyResolveMode)
|
||||
return if (this is KtParameter && hasValOrVar()) {
|
||||
context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, this)
|
||||
} else {
|
||||
context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtClassOrObject.resolveToDescriptorIfAny(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): ClassDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(resolutionFacade, bodyResolveMode) as? ClassDescriptor
|
||||
}
|
||||
|
||||
fun KtNamedFunction.resolveToDescriptorIfAny(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): FunctionDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(resolutionFacade, bodyResolveMode) as? FunctionDescriptor
|
||||
}
|
||||
|
||||
fun KtProperty.resolveToDescriptorIfAny(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): VariableDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(resolutionFacade, bodyResolveMode) as? VariableDescriptor
|
||||
}
|
||||
|
||||
fun KtParameter.resolveToParameterDescriptorIfAny(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): ValueParameterDescriptor? {
|
||||
val context = analyze(resolutionFacade, bodyResolveMode)
|
||||
return context.get(BindingContext.VALUE_PARAMETER, this) as? ValueParameterDescriptor
|
||||
}
|
||||
|
||||
fun KtElement.resolveToCall(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): ResolvedCall<out CallableDescriptor>? =
|
||||
getResolvedCall(analyze(resolutionFacade, bodyResolveMode))
|
||||
|
||||
|
||||
@JvmOverloads
|
||||
fun KtElement.analyze(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL
|
||||
): BindingContext =
|
||||
resolutionFacade.analyze(this, bodyResolveMode)
|
||||
|
||||
fun KtElement.analyzeAndGetResult(resolutionFacade: ResolutionFacade): AnalysisResult {
|
||||
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
|
||||
}
|
||||
|
||||
// This function is used on declarations to make analysis not only declaration itself but also it content:
|
||||
// body for declaration with body, initializer & accessors for properties
|
||||
fun KtDeclaration.analyzeWithContent(resolutionFacade: ResolutionFacade): BindingContext =
|
||||
resolutionFacade.analyzeWithAllCompilerChecks(listOf(this)).bindingContext
|
||||
|
||||
// This function is used to make full analysis of declaration container.
|
||||
// All its declarations, including their content (see above), are analyzed.
|
||||
inline fun <reified T> T.analyzeWithContent(resolutionFacade: ResolutionFacade): BindingContext where T : KtDeclarationContainer, T : KtElement =
|
||||
resolutionFacade.analyzeWithAllCompilerChecks(listOf(this)).bindingContext
|
||||
|
||||
@@ -28,64 +28,74 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
||||
|
||||
fun KtElement.getResolutionFacade(): ResolutionFacade =
|
||||
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this))
|
||||
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this))
|
||||
|
||||
/**
|
||||
* For local declarations is equivalent to unsafeResolveToDescriptor(bodyResolveMode)
|
||||
*
|
||||
* But for non-local declarations it ignores bodyResolveMode and uses LazyDeclarationResolver directly
|
||||
*/
|
||||
@Deprecated(message = "This function has unclear semantics. Please use either unsafeResolveToDescriptor or resolveToDescriptorIfAny instead",
|
||||
replaceWith = ReplaceWith("unsafeResolveToDescriptor"))
|
||||
@Deprecated(
|
||||
message = "This function has unclear semantics. Please use either unsafeResolveToDescriptor or resolveToDescriptorIfAny instead",
|
||||
replaceWith = ReplaceWith("unsafeResolveToDescriptor")
|
||||
)
|
||||
fun KtDeclaration.resolveToDescriptor(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): DeclarationDescriptor =
|
||||
getResolutionFacade().resolveToDescriptor(this, bodyResolveMode)
|
||||
getResolutionFacade().resolveToDescriptor(this, bodyResolveMode)
|
||||
|
||||
/**
|
||||
* This function throws exception when resolveToDescriptorIfAny returns null, otherwise works equivalently.
|
||||
*
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtDeclaration.unsafeResolveToDescriptor(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): DeclarationDescriptor =
|
||||
resolveToDescriptorIfAny(bodyResolveMode) ?: throw NoDescriptorForDeclarationException(this)
|
||||
fun KtDeclaration.unsafeResolveToDescriptor(
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL
|
||||
): DeclarationDescriptor =
|
||||
unsafeResolveToDescriptor(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
/**
|
||||
* This function first uses declaration resolvers to resolve this declaration and/or additional declarations (e.g. its parent),
|
||||
* and then takes the relevant descriptor from binding context.
|
||||
* The exact set of declarations to resolve depends on bodyResolveMode
|
||||
*
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtDeclaration.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): DeclarationDescriptor? {
|
||||
//TODO: BodyResolveMode.PARTIAL is not quite safe!
|
||||
val context = analyze(bodyResolveMode)
|
||||
return if (this is KtParameter && hasValOrVar()) {
|
||||
context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, this)
|
||||
} else {
|
||||
context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
||||
}
|
||||
}
|
||||
fun KtDeclaration.resolveToDescriptorIfAny(
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||
): DeclarationDescriptor? =
|
||||
resolveToDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtClassOrObject.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): ClassDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(bodyResolveMode) as? ClassDescriptor
|
||||
}
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtClassOrObject.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL) =
|
||||
resolveToDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtNamedFunction.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): FunctionDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(bodyResolveMode) as? FunctionDescriptor
|
||||
}
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtNamedFunction.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL) =
|
||||
resolveToDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtProperty.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): VariableDescriptor? {
|
||||
return (this as KtDeclaration).resolveToDescriptorIfAny(bodyResolveMode) as? VariableDescriptor
|
||||
}
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtProperty.resolveToDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL) =
|
||||
resolveToDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtParameter.resolveToParameterDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): ValueParameterDescriptor? {
|
||||
val context = analyze(bodyResolveMode)
|
||||
return context.get(BindingContext.VALUE_PARAMETER, this) as? ValueParameterDescriptor
|
||||
}
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtParameter.resolveToParameterDescriptorIfAny(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL) =
|
||||
resolveToParameterDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtElement.resolveToCall(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL): ResolvedCall<out CallableDescriptor>? =
|
||||
getResolvedCall(analyze(bodyResolveMode))
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtElement.resolveToCall(bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL) =
|
||||
resolveToCall(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
fun KtFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescriptor> {
|
||||
val facade = getResolutionFacade()
|
||||
@@ -111,26 +121,39 @@ fun KtFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescrip
|
||||
// BodyResolveMode.PARTIAL analyzes only statements necessary for this KtElement precise analysis.
|
||||
//
|
||||
// See also: ResolveSessionForBodies, ResolveElementCache
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun KtElement.analyze(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext =
|
||||
getResolutionFacade().analyze(this, bodyResolveMode)
|
||||
fun KtElement.analyze(
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL
|
||||
): BindingContext =
|
||||
analyze(getResolutionFacade(), bodyResolveMode)
|
||||
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtElement.analyzeAndGetResult(): AnalysisResult {
|
||||
val resolutionFacade = getResolutionFacade()
|
||||
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
|
||||
return analyzeAndGetResult(getResolutionFacade())
|
||||
}
|
||||
|
||||
fun KtElement.findModuleDescriptor(): ModuleDescriptor = getResolutionFacade().moduleDescriptor
|
||||
|
||||
// This function is used on declarations to make analysis not only declaration itself but also it content:
|
||||
// body for declaration with body, initializer & accessors for properties
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
fun KtDeclaration.analyzeWithContent(): BindingContext =
|
||||
getResolutionFacade().analyzeWithAllCompilerChecks(listOf(this)).bindingContext
|
||||
analyzeWithContent(getResolutionFacade())
|
||||
|
||||
// This function is used to make full analysis of declaration container.
|
||||
// All its declarations, including their content (see above), are analyzed.
|
||||
/**
|
||||
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||
*/
|
||||
inline fun <reified T> T.analyzeWithContent(): BindingContext where T : KtDeclarationContainer, T : KtElement =
|
||||
getResolutionFacade().analyzeWithAllCompilerChecks(listOf(this)).bindingContext
|
||||
analyzeWithContent(getResolutionFacade())
|
||||
|
||||
/**
|
||||
* This function is expected to produce the same result as compiler for the whole file content (including diagnostics,
|
||||
|
||||
Reference in New Issue
Block a user