JetReference.resolveToDescriptors() requires BindingContext

This commit is contained in:
Valentin Kipyatkov
2015-03-24 17:10:56 +03:00
parent 04a6ebf0d6
commit 6dc943a739
8 changed files with 66 additions and 66 deletions
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiReference<JetMultiDeclaration>(element) {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
@@ -39,7 +40,8 @@ class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiRefer
}
override fun canRename(): Boolean {
return resolveToDescriptors().all { it is CallableMemberDescriptor && it.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED}
val bindingContext = expression.analyze() //TODO: should it use full body resolve?
return resolveToDescriptors(bindingContext).all { it is CallableMemberDescriptor && it.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED}
}
override fun handleElementRename(newElementName: String?): PsiElement? {
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
public trait JetReference : PsiPolyVariantReference {
public fun resolveToDescriptors(): Collection<DeclarationDescriptor>
public fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor>
}
public abstract class AbstractJetReference<T : JetElement>(element: T)
@@ -72,8 +72,8 @@ public abstract class AbstractJetReference<T : JetElement>(element: T)
return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext))
}
override fun resolveToDescriptors(): Collection<DeclarationDescriptor> {
return getTargetDescriptors(expression.analyze())
override fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
return getTargetDescriptors(bindingContext)
}
private fun resolveToPsiElements(context: BindingContext, targetDescriptors: Collection<DeclarationDescriptor>): Collection<PsiElement> {
@@ -119,7 +119,7 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<Kotlin
val reference = element.getReference() as? JetReference ?: return listOf()
val descriptors = reference.resolveToDescriptors()
val descriptors = reference.resolveToDescriptors((element as JetElement).analyze()) //TODO: we could use partial body resolve for all references together
//check whether this reference is unambiguous
if (reference !is JetMultiReference<*> && descriptors.size() > 1) return listOf()
@@ -231,7 +231,7 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<Kotlin
private fun createReferenceToRestoreData(element: JetElement, refData: KotlinReferenceData): ReferenceToRestoreData? {
val reference = element.getReference() as? JetReference ?: return null
val referencedDescriptors = try {
reference.resolveToDescriptors()
reference.resolveToDescriptors(element.analyze()) //TODO: we could use partial body resolve for all references together
}
catch (e: Throwable) {
LOG.error("Failed to analyze reference (${element.getText()}) after copy paste", e)
@@ -92,9 +92,8 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
}
}
protected val bindingContext: BindingContext? = expression?.let { resolutionFacade.analyze(it, BodyResolveMode.PARTIAL_FOR_COMPLETION) }
protected val inDescriptor: DeclarationDescriptor? = expression?.let { bindingContext!!.get(BindingContext.RESOLUTION_SCOPE, it)?.getContainingDeclaration() }
protected val bindingContext: BindingContext = resolutionFacade.analyze(position.getParent() as JetElement, BodyResolveMode.PARTIAL_FOR_COMPLETION)
protected val inDescriptor: DeclarationDescriptor? = expression?.let { bindingContext.get(BindingContext.RESOLUTION_SCOPE, it)?.getContainingDeclaration() }
private fun singleCharPattern(char: Char): CharPattern {
return StandardPatterns.character().with(
@@ -130,14 +129,13 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
protected val referenceVariantsHelper: ReferenceVariantsHelper?
= if (bindingContext != null) ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) } else null
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) }
protected val lookupElementFactory: LookupElementFactory = run {
val receiverTypes = if (reference != null) {
val expression = reference.expression
val (receivers, callType) = referenceVariantsHelper!!.getReferenceVariantsReceivers(expression)
val dataFlowInfo = bindingContext!!.getDataFlowInfo(expression)
val (receivers, callType) = referenceVariantsHelper.getReferenceVariantsReceivers(expression)
val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
var receiverTypes = receivers.flatMap {
SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, moduleDescriptor, dataFlowInfo)
}
@@ -165,7 +163,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
}
protected val indicesHelper: KotlinIndicesHelper
get() = KotlinIndicesHelper(project, resolutionFacade, bindingContext!!, searchScope, moduleDescriptor) { isVisibleDescriptor(it) }
get() = KotlinIndicesHelper(project, resolutionFacade, bindingContext, searchScope, moduleDescriptor) { isVisibleDescriptor(it) }
protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean {
if (descriptor is DeclarationDescriptorWithVisibility && inDescriptor != null) {
@@ -194,7 +192,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
private var alreadyAddedDescriptors: Collection<DeclarationDescriptor> by Delegates.notNull()
protected fun getReferenceVariants(kindFilter: DescriptorKindFilter, runtimeReceiverType: Boolean): Collection<DeclarationDescriptor> {
val descriptors = referenceVariantsHelper!!.getReferenceVariants(reference!!.expression, kindFilter, runtimeReceiverType, prefixMatcher.asNameFilter())
val descriptors = referenceVariantsHelper.getReferenceVariants(reference!!.expression, kindFilter, runtimeReceiverType, prefixMatcher.asNameFilter())
if (!runtimeReceiverType) {
if (position.getContainingFile() is JetCodeFragment) {
alreadyAddedDescriptors = descriptors
@@ -229,7 +227,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) {
AllClassesCompletion(
parameters, lookupElementFactory, resolutionFacade, bindingContext!!, moduleDescriptor,
parameters, lookupElementFactory, resolutionFacade, bindingContext, moduleDescriptor,
searchScope, prefixMatcher, kindFilter, { isVisibleDescriptor(it) }
).collect(collector)
}
@@ -311,7 +309,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
"this" -> {
if (expression != null) {
collector.addElements(thisExpressionItems(bindingContext!!, expression, prefix).map { it.factory() })
collector.addElements(thisExpressionItems(bindingContext, expression, prefix).map { it.factory() })
}
else {
// for completion in secondary constructor delegation call
@@ -322,7 +320,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
// if "return" is parsed correctly in the current context - insert it and all return@xxx items
"return" -> {
if (expression != null) {
collector.addElements(returnExpressionItems(bindingContext!!, expression))
collector.addElements(returnExpressionItems(bindingContext, expression))
}
}
@@ -351,7 +349,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
}
}
NamedParametersCompletion.complete(position, collector)
NamedParametersCompletion.complete(position, collector, bindingContext)
}
private object NonAnnotationClassifierExclude : DescriptorKindExclude {
@@ -400,7 +398,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
if (expression != null) {
val mapper = ToFromOriginalFileMapper(parameters.getOriginalFile() as JetFile, position.getContainingFile() as JetFile, parameters.getOffset())
val completion = SmartCompletion(expression, resolutionFacade, moduleDescriptor,
bindingContext!!, { isVisibleDescriptor(it) }, inDescriptor, prefixMatcher, originalSearchScope,
bindingContext, { isVisibleDescriptor(it) }, inDescriptor, prefixMatcher, originalSearchScope,
mapper, lookupElementFactory)
val result = completion.execute()
if (result != null) {
@@ -16,30 +16,31 @@
package org.jetbrains.kotlin.idea.completion
import org.jetbrains.kotlin.psi.JetValueArgument
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetCallElement
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import com.intellij.codeInsight.lookup.LookupElementBuilder
import org.jetbrains.kotlin.idea.JetIcons
import org.jetbrains.kotlin.idea.quickfix.QuickFixUtil
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.psi.filters.AndFilter
import org.jetbrains.kotlin.psi.JetValueArgumentName
import com.intellij.psi.filters.position.ParentElementFilter
import com.intellij.psi.filters.OrFilter
import com.intellij.psi.filters.ClassFilter
import org.jetbrains.kotlin.idea.util.FirstChildInParentFilter
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import com.intellij.psi.PsiElement
import com.intellij.codeInsight.completion.InsertHandler
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.psi.PsiElement
import com.intellij.psi.filters.AndFilter
import com.intellij.psi.filters.ClassFilter
import com.intellij.psi.filters.OrFilter
import com.intellij.psi.filters.position.ParentElementFilter
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.JetIcons
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
import org.jetbrains.kotlin.idea.quickfix.QuickFixUtil
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.idea.util.FirstChildInParentFilter
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetCallElement
import org.jetbrains.kotlin.psi.JetValueArgument
import org.jetbrains.kotlin.psi.JetValueArgumentName
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
object NamedParametersCompletion {
private val positionFilter = AndFilter(
@@ -68,7 +69,7 @@ object NamedParametersCompletion {
return false
}
public fun complete(position: PsiElement, collector: LookupElementsCollector) {
public fun complete(position: PsiElement, collector: LookupElementsCollector, bindingContext: BindingContext) {
if (!positionFilter.isAcceptable(position, position)) return
val valueArgument = position.getStrictParentOfType<JetValueArgument>()!!
@@ -78,7 +79,7 @@ object NamedParametersCompletion {
val callReference = callSimpleName.getReference() as JetReference
val functionDescriptors = callReference.resolveToDescriptors().map { it as? FunctionDescriptor }.filterNotNull()
val functionDescriptors = callReference.resolveToDescriptors(bindingContext).map { it as? FunctionDescriptor }.filterNotNull()
for (funDescriptor in functionDescriptors) {
if (!funDescriptor.hasStableParameterNames()) continue
@@ -182,19 +182,15 @@ public class KotlinImportOptimizer() : ImportOptimizer {
override fun visitPackageDirective(directive: JetPackageDirective) {
}
private fun JetElement.classForCompanionObjectReference(): ClassDescriptor? {
return analyze()[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, this as? JetReferenceExpression]
}
override fun visitJetElement(element: JetElement) {
val reference = element.getReference()
if (reference is JetReference) {
val referencedName = (element as? JetNameReferenceExpression)?.getReferencedNameAsName() //TODO: other types of references
val bindingContext = element.analyze()
//class qualifiers that refer to companion objects should be considered (containing) class references
val targets = element.classForCompanionObjectReference()?.let { listOf(it) }
?: reference.resolveToDescriptors()
val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element as? JetReferenceExpression]?.let { listOf(it) }
?: reference.resolveToDescriptors(bindingContext)
for (target in targets) {
if (!target.canBeReferencedViaImport()) continue
if (target is PackageViewDescriptor && target.getFqName().parent() == FqName.ROOT) continue // no need to import top-level packages
@@ -20,16 +20,18 @@ import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.refactoring.rename.RenameProcessor
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.JetBundle
import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBaseIntentionAction() {
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
@@ -73,7 +75,7 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
}
is JetSimpleNameExpression -> {
val reference = expression.getReference() as JetReference?
val variableDescriptor = reference?.resolveToDescriptors()?.firstOrNull() as? VariableDescriptor?
val variableDescriptor = reference?.resolveToDescriptors(expression.analyze(BodyResolveMode.PARTIAL))?.firstOrNull() as? VariableDescriptor?
if (variableDescriptor != null) {
val containingDescriptor = variableDescriptor.getContainingDeclaration()
if (containingDescriptor is AnonymousFunctionDescriptor) {
@@ -22,24 +22,25 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.psi.JetFunctionLiteral
import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.JetFunctionLiteral
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class ReplaceItWithExplicitFunctionLiteralParamIntention() : PsiElementBaseIntentionAction() {
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
val simpleNameExpression = element.getStrictParentOfType<JetSimpleNameExpression>()!!
val simpleNameReference = simpleNameExpression.getReference() as JetReference?
val target = simpleNameReference?.resolveToDescriptors()?.first()!!
val target = simpleNameReference?.resolveToDescriptors(simpleNameExpression.analyze(BodyResolveMode.PARTIAL))?.first()!!
val funcExpr = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as JetFunctionLiteral
@@ -74,9 +75,9 @@ public class ReplaceItWithExplicitFunctionLiteralParamIntention() : PsiElementBa
return false
}
val bindingContext = simpleNameExpression.analyze()
val bindingContext = simpleNameExpression.analyze(BodyResolveMode.PARTIAL)
val reference = simpleNameExpression.getReference() as JetReference?
val simpleNameTarget = reference?.resolveToDescriptors()?.firstOrNull() as? ValueParameterDescriptor?
val simpleNameTarget = reference?.resolveToDescriptors(bindingContext)?.firstOrNull() as? ValueParameterDescriptor?
if (simpleNameTarget == null || bindingContext.get(BindingContext.AUTO_CREATED_IT, simpleNameTarget) != true) {
return false
}