Using PsiElement.getResolutionScope instead of LEXICAL_SCOPE from BindingContext

This commit is contained in:
Valentin Kipyatkov
2015-10-25 13:42:50 +03:00
parent 6af71caaa9
commit 95a0372b43
10 changed files with 29 additions and 26 deletions
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
@@ -117,7 +116,7 @@ public class ReferenceVariantsHelper(
} }
is CallTypeAndReceiver.CALLABLE_REFERENCE -> { is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
val resolutionScope = context[BindingContext.LEXICAL_SCOPE, expression.parent as KtExpression] ?: return emptyList() val resolutionScope = expression.getResolutionScope(context, resolutionFacade)
return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, kindFilter, nameFilter) return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, kindFilter, nameFilter)
} }
@@ -130,7 +129,7 @@ public class ReferenceVariantsHelper(
else -> throw RuntimeException() //TODO: see KT-9394 else -> throw RuntimeException() //TODO: see KT-9394
} }
val resolutionScope = context[BindingContext.LEXICAL_SCOPE, expression] ?: return emptyList() val resolutionScope = expression.getResolutionScope(context, resolutionFacade)
val dataFlowInfo = context.getDataFlowInfo(expression) val dataFlowInfo = context.getDataFlowInfo(expression)
val containingDeclaration = resolutionScope.ownerDescriptor val containingDeclaration = resolutionScope.ownerDescriptor
@@ -180,10 +179,8 @@ public class ReferenceVariantsHelper(
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter) return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
} }
else { else {
val lexicalScope = expression.getParentOfType<KtTypeReference>(strict = true)?.let { val scope = expression.getResolutionScope(context, resolutionFacade)
context[BindingContext.LEXICAL_SCOPE, it] return scope.collectDescriptorsFiltered(kindFilter, nameFilter)
} ?: return emptyList()
return lexicalScope.collectDescriptorsFiltered(kindFilter, nameFilter)
} }
} }
@@ -335,7 +332,7 @@ public class ReferenceVariantsHelper(
expression: KtSimpleNameExpression, expression: KtSimpleNameExpression,
nameFilter: (Name) -> Boolean nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
val resolutionScope = context[BindingContext.LEXICAL_SCOPE, expression] ?: return listOf() val resolutionScope = expression.getResolutionScope(context, resolutionFacade)
return resolutionScope.collectDescriptorsFiltered(DescriptorKindFilter.PACKAGES, nameFilter).filter(visibilityFilter) return resolutionScope.collectDescriptorsFiltered(DescriptorKindFilter.PACKAGES, nameFilter).filter(visibilityFilter)
} }
} }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
@@ -187,6 +188,7 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
bindingContext: BindingContext, bindingContext: BindingContext,
position: KtExpression, position: KtExpression,
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
resolutionFacade: ResolutionFacade,
predictableSmartCastsOnly: Boolean predictableSmartCastsOnly: Boolean
): Collection<KotlinType>? { ): Collection<KotlinType>? {
val receiverExpression: KtExpression? val receiverExpression: KtExpression?
@@ -218,7 +220,7 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList() expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList()
} }
else { else {
val resolutionScope = bindingContext[BindingContext.LEXICAL_SCOPE, position] ?: return emptyList() val resolutionScope = position.getResolutionScope(bindingContext, resolutionFacade)
resolutionScope.getImplicitReceiversWithInstance().map { it.value } resolutionScope.getImplicitReceiversWithInstance().map { it.value }
} }
@@ -188,14 +188,14 @@ public class ShadowedDeclarationsFilter private constructor(
override fun getCallType() = Call.CallType.DEFAULT override fun getCallType() = Call.CallType.DEFAULT
} }
var lexicalScope = bindingContext[BindingContext.LEXICAL_SCOPE, context] ?: return descriptors var scope = context.getResolutionScope(bindingContext, resolutionFacade)
if (descriptorsToImport.isNotEmpty()) { if (descriptorsToImport.isNotEmpty()) {
lexicalScope = lexicalScope.addImportScope(ExplicitImportsScope(descriptorsToImport)) scope = scope.addImportScope(ExplicitImportsScope(descriptorsToImport))
} }
val dataFlowInfo = bindingContext.getDataFlowInfo(context) val dataFlowInfo = bindingContext.getDataFlowInfo(context)
val context = BasicCallResolutionContext.create(bindingTrace, lexicalScope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, val context = BasicCallResolutionContext.create(bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
CallChecker.DoNothing, false) CallChecker.DoNothing, false)
val callResolver = resolutionFacade.frontendService<CallResolver>() val callResolver = resolutionFacade.frontendService<CallResolver>()
@@ -58,7 +58,7 @@ public fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDe
return null return null
} }
public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade): LexicalScope { public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/): LexicalScope {
for (parent in parentsWithSelf) { for (parent in parentsWithSelf) {
if (parent is KtElement) { if (parent is KtElement) {
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent] val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent]
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -203,7 +202,7 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
private val elementsToShorten = ArrayList<T>() private val elementsToShorten = ArrayList<T>()
private val descriptorsToImport = LinkedHashSet<DeclarationDescriptor>() private val descriptorsToImport = LinkedHashSet<DeclarationDescriptor>()
private val resolutionFacade = file.getResolutionFacade() protected val resolutionFacade = file.getResolutionFacade()
protected fun analyze(element: KtElement) protected fun analyze(element: KtElement)
= resolutionFacade.analyze(element, BodyResolveMode.PARTIAL) = resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
@@ -274,8 +273,7 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
val bindingContext = analyze(referenceExpression) val bindingContext = analyze(referenceExpression)
val target = referenceExpression.targets(bindingContext).singleOrNull() ?: return val target = referenceExpression.targets(bindingContext).singleOrNull() ?: return
val typeReference = type.getStrictParentOfType<KtTypeReference>()!! val scope = type.getResolutionScope(bindingContext, resolutionFacade)
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, typeReference] ?: return
val name = target.getName() val name = target.getName()
val targetByName = if (target is ClassifierDescriptor) val targetByName = if (target is ClassifierDescriptor)
scope.findClassifier(name, NoLookupLocation.FROM_IDE) scope.findClassifier(name, NoLookupLocation.FROM_IDE)
@@ -344,7 +342,7 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return false val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return false
val target = callee.targets(bindingContext).singleOrNull() ?: return false val target = callee.targets(bindingContext).singleOrNull() ?: return false
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, qualifiedExpression] ?: return false val scope = qualifiedExpression.getResolutionScope(bindingContext, resolutionFacade)
val selectorCopy = selector.copy() as KtReferenceExpression val selectorCopy = selector.copy() as KtReferenceExpression
val newContext = selectorCopy.analyzeInContext(scope, selector) val newContext = selectorCopy.analyzeInContext(scope, selector)
val targetsWhenShort = (selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression).targets(newContext) val targetsWhenShort = (selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression).targets(newContext)
@@ -392,7 +390,7 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
val bindingContext = analyze(thisExpression) val bindingContext = analyze(thisExpression)
val targetBefore = thisExpression.getInstanceReference().targets(bindingContext).singleOrNull() ?: return val targetBefore = thisExpression.getInstanceReference().targets(bindingContext).singleOrNull() ?: return
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, thisExpression] ?: return val scope = thisExpression.getResolutionScope(bindingContext, resolutionFacade)
val newContext = simpleThis.analyzeInContext(scope, thisExpression) val newContext = simpleThis.analyzeInContext(scope, thisExpression)
val targetAfter = simpleThis.getInstanceReference().targets(newContext).singleOrNull() val targetAfter = simpleThis.getInstanceReference().targets(newContext).singleOrNull()
if (targetBefore == targetAfter) { if (targetBefore == targetAfter) {
@@ -31,7 +31,10 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
import org.jetbrains.kotlin.idea.core.* import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier
import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper
import org.jetbrains.kotlin.idea.core.compareDescriptors
import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
@@ -332,7 +335,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression) val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression)
var receiverTypes = callTypeAndReceiver.receiverTypes( var receiverTypes = callTypeAndReceiver.receiverTypes(
bindingContext, nameExpression, moduleDescriptor, bindingContext, nameExpression, moduleDescriptor, resolutionFacade,
predictableSmartCastsOnly = true /* we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed */) predictableSmartCastsOnly = true /* we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed */)
if (callTypeAndReceiver is CallTypeAndReceiver.SAFE) { if (callTypeAndReceiver is CallTypeAndReceiver.SAFE) {
@@ -95,7 +95,7 @@ public class KotlinIndicesHelper(
position: KtExpression, position: KtExpression,
bindingContext: BindingContext bindingContext: BindingContext
): Collection<CallableDescriptor> { ): Collection<CallableDescriptor> {
val receiverTypes = callTypeAndReceiver.receiverTypes(bindingContext, position, moduleDescriptor, predictableSmartCastsOnly = false) val receiverTypes = callTypeAndReceiver.receiverTypes(bindingContext, position, moduleDescriptor, resolutionFacade, predictableSmartCastsOnly = false)
if (receiverTypes == null || receiverTypes.isEmpty()) return emptyList() if (receiverTypes == null || receiverTypes.isEmpty()) return emptyList()
val receiverTypeNames = HashSet<String>() val receiverTypeNames = HashSet<String>()
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
@@ -114,7 +114,7 @@ public class RedundantSamConstructorInspection : AbstractKotlinInspection() {
val context = parentCall.analyze(BodyResolveMode.PARTIAL) val context = parentCall.analyze(BodyResolveMode.PARTIAL)
val calleeExpression = parentCall.calleeExpression ?: return false val calleeExpression = parentCall.calleeExpression ?: return false
val scope = context[BindingContext.LEXICAL_SCOPE, calleeExpression] ?: return false val scope = calleeExpression.getResolutionScope(context, calleeExpression.getResolutionFacade())
val originalCall = parentCall.getResolvedCall(context) ?: return false val originalCall = parentCall.getResolvedCall(context) ?: return false
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.BindingTraceContext
@@ -47,7 +48,7 @@ public class RemoveExplicitTypeArgumentsIntention : JetSelfTargetingOffsetIndepe
val resolutionFacade = callExpression.getResolutionFacade() val resolutionFacade = callExpression.getResolutionFacade()
val context = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL) val context = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL)
val calleeExpression = callExpression.getCalleeExpression() ?: return false val calleeExpression = callExpression.getCalleeExpression() ?: return false
val scope = context[BindingContext.LEXICAL_SCOPE, calleeExpression/*TODO: discuss it*/] ?: return false val scope = calleeExpression.getResolutionScope(context, resolutionFacade)
val originalCall = callExpression.getResolvedCall(context) ?: return false val originalCall = callExpression.getResolvedCall(context) ?: return false
val untypedCall = CallWithoutTypeArgs(originalCall.getCall()) val untypedCall = CallWithoutTypeArgs(originalCall.getCall())
@@ -23,10 +23,12 @@ import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver
import org.jetbrains.kotlin.idea.core.compareDescriptors import org.jetbrains.kotlin.idea.core.compareDescriptors
import org.jetbrains.kotlin.idea.core.refactoring.getContextForContainingDeclarationBody import org.jetbrains.kotlin.idea.core.refactoring.getContextForContainingDeclarationBody
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
@@ -179,7 +181,7 @@ data class ExtractionData(
} }
val type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet() val type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet()
val containingDescriptor = context[BindingContext.LEXICAL_SCOPE, expression]?.ownerDescriptor ?: return emptySet() val containingDescriptor = expression.getResolutionScope(context, expression.getResolutionFacade()).ownerDescriptor
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor) val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor)
return typeInfo.dataFlowInfo.getPossibleTypes(dataFlowValue) return typeInfo.dataFlowInfo.getPossibleTypes(dataFlowValue)
} }