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.BindingTraceContext
|
||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
|
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.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
|
||||||
|
|
||||||
fun KtElement.getResolutionFacade(): ResolutionFacade =
|
fun KtElement.getResolutionFacade(): ResolutionFacade =
|
||||||
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this))
|
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For local declarations is equivalent to unsafeResolveToDescriptor(bodyResolveMode)
|
* For local declarations is equivalent to unsafeResolveToDescriptor(bodyResolveMode)
|
||||||
*
|
*
|
||||||
* But for non-local declarations it ignores bodyResolveMode and uses LazyDeclarationResolver directly
|
* 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",
|
@Deprecated(
|
||||||
replaceWith = ReplaceWith("unsafeResolveToDescriptor"))
|
message = "This function has unclear semantics. Please use either unsafeResolveToDescriptor or resolveToDescriptorIfAny instead",
|
||||||
|
replaceWith = ReplaceWith("unsafeResolveToDescriptor")
|
||||||
|
)
|
||||||
fun KtDeclaration.resolveToDescriptor(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): DeclarationDescriptor =
|
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.
|
* 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 =
|
fun KtDeclaration.unsafeResolveToDescriptor(
|
||||||
resolveToDescriptorIfAny(bodyResolveMode) ?: throw NoDescriptorForDeclarationException(this)
|
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),
|
* 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.
|
* and then takes the relevant descriptor from binding context.
|
||||||
* The exact set of declarations to resolve depends on bodyResolveMode
|
* 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? {
|
fun KtDeclaration.resolveToDescriptorIfAny(
|
||||||
//TODO: BodyResolveMode.PARTIAL is not quite safe!
|
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL
|
||||||
val context = analyze(bodyResolveMode)
|
): DeclarationDescriptor? =
|
||||||
return if (this is KtParameter && hasValOrVar()) {
|
resolveToDescriptorIfAny(getResolutionFacade(), bodyResolveMode)
|
||||||
context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, this)
|
|
||||||
} else {
|
|
||||||
context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||||
return context.get(BindingContext.VALUE_PARAMETER, this) as? ValueParameterDescriptor
|
*/
|
||||||
}
|
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> {
|
fun KtFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
val facade = getResolutionFacade()
|
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.
|
// BodyResolveMode.PARTIAL analyzes only statements necessary for this KtElement precise analysis.
|
||||||
//
|
//
|
||||||
// See also: ResolveSessionForBodies, ResolveElementCache
|
// See also: ResolveSessionForBodies, ResolveElementCache
|
||||||
|
/**
|
||||||
|
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||||
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun KtElement.analyze(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext =
|
fun KtElement.analyze(
|
||||||
getResolutionFacade().analyze(this, bodyResolveMode)
|
bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL
|
||||||
|
): BindingContext =
|
||||||
|
analyze(getResolutionFacade(), bodyResolveMode)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Please, use overload with providing resolutionFacade for stable results of subsequent calls**
|
||||||
|
*/
|
||||||
fun KtElement.analyzeAndGetResult(): AnalysisResult {
|
fun KtElement.analyzeAndGetResult(): AnalysisResult {
|
||||||
val resolutionFacade = getResolutionFacade()
|
return analyzeAndGetResult(getResolutionFacade())
|
||||||
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtElement.findModuleDescriptor(): ModuleDescriptor = getResolutionFacade().moduleDescriptor
|
fun KtElement.findModuleDescriptor(): ModuleDescriptor = getResolutionFacade().moduleDescriptor
|
||||||
|
|
||||||
// This function is used on declarations to make analysis not only declaration itself but also it content:
|
// 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
|
// 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 =
|
fun KtDeclaration.analyzeWithContent(): BindingContext =
|
||||||
getResolutionFacade().analyzeWithAllCompilerChecks(listOf(this)).bindingContext
|
analyzeWithContent(getResolutionFacade())
|
||||||
|
|
||||||
// This function is used to make full analysis of declaration container.
|
// This function is used to make full analysis of declaration container.
|
||||||
// All its declarations, including their content (see above), are analyzed.
|
// 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 =
|
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,
|
* 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