Added utility functions for functions and variables in scope

This commit is contained in:
Valentin Kipyatkov
2015-10-25 12:26:50 +03:00
parent 5f06f53bfd
commit c09cf63424
11 changed files with 66 additions and 59 deletions
@@ -97,6 +97,26 @@ public fun LexicalScope.findClassifier(name: Name, location: LookupLocation): Cl
public fun LexicalScope.findPackage(name: Name): PackageViewDescriptor? public fun LexicalScope.findPackage(name: Name): PackageViewDescriptor?
= findFirstFromImportingScopes { it.getContributedPackage(name) } = findFirstFromImportingScopes { it.getContributedPackage(name) }
public fun LexicalScope.collectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor>
= collectAllFromMeAndParent { it.getContributedVariables(name, location) }
public fun LexicalScope.collectFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor>
= collectAllFromMeAndParent { it.getContributedFunctions(name, location) }
public fun LexicalScope.findVariable(name: Name, location: LookupLocation, predicate: (VariableDescriptor) -> Boolean = { true }): VariableDescriptor? {
processForMeAndParent {
it.getContributedVariables(name, location).firstOrNull(predicate)?.let { return it }
}
return null
}
public fun LexicalScope.findFunction(name: Name, location: LookupLocation, predicate: (FunctionDescriptor) -> Boolean = { true }): FunctionDescriptor? {
processForMeAndParent {
it.getContributedFunctions(name, location).firstOrNull(predicate)?.let { return it }
}
return null
}
public fun LexicalScope.takeSnapshot(): LexicalScope = if (this is LexicalWritableScope) takeSnapshot() else this public fun LexicalScope.takeSnapshot(): LexicalScope = if (this is LexicalWritableScope) takeSnapshot() else this
public fun LexicalScope.asKtScope(): KtScope { public fun LexicalScope.asKtScope(): KtScope {
@@ -128,9 +148,8 @@ private class LexicalToKtScopeAdapter(lexicalScope: LexicalScope): KtScope {
return lexicalScope.collectAllFromImportingScopes { it.getContributedVariables(name, location) } return lexicalScope.collectAllFromImportingScopes { it.getContributedVariables(name, location) }
} }
override fun getFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> { override fun getFunctions(name: Name, location: LookupLocation)
return lexicalScope.collectAllFromMeAndParent { it.getContributedFunctions(name, location) } = lexicalScope.collectFunctions(name, location)
}
override fun getLocalVariable(name: Name) = lexicalScope.findLocalVariable(name) override fun getLocalVariable(name: Name) = lexicalScope.findLocalVariable(name)
@@ -23,16 +23,17 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
public fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescriptor> { public fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescriptor> {
return getVariablesFromImplicitReceivers(name) + collectAllFromMeAndParent { it.getContributedVariables(name, NoLookupLocation.FROM_IDE) } return getVariablesFromImplicitReceivers(name) + collectVariables(name, NoLookupLocation.FROM_IDE)
} }
public fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> { public fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> {
return getImplicitReceiversWithInstance().flatMap { it.type.memberScope.getFunctions(name, NoLookupLocation.FROM_IDE) } + return getImplicitReceiversWithInstance().flatMap { it.type.memberScope.getFunctions(name, NoLookupLocation.FROM_IDE) } +
collectAllFromMeAndParent { it.getContributedFunctions(name, NoLookupLocation.FROM_IDE) } collectFunctions(name, NoLookupLocation.FROM_IDE)
} }
public fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap { public fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap {
@@ -36,9 +36,9 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
import org.jetbrains.kotlin.resolve.scopes.utils.findLocalVariable
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.* import java.util.*
@@ -106,8 +106,7 @@ class MultipleArgumentsItemProvider(
private fun variableInScope(parameter: ValueParameterDescriptor, scope: LexicalScope): VariableDescriptor? { private fun variableInScope(parameter: ValueParameterDescriptor, scope: LexicalScope): VariableDescriptor? {
val name = parameter.getName() val name = parameter.getName()
//TODO: there can be more than one property with such name in scope and we should be able to select one (but we need API for this) //TODO: there can be more than one property with such name in scope and we should be able to select one (but we need API for this)
val variable = scope.findLocalVariable(name) val variable = scope.findVariable(name, NoLookupLocation.FROM_IDE) { !it.isExtension }
?: scope.collectAllFromMeAndParent { it.getContributedVariables(name, NoLookupLocation.FROM_IDE) }.singleOrNull()
?: scope.getVariableFromImplicitReceivers(name) ?: return null ?: scope.getVariableFromImplicitReceivers(name) ?: return null
return if (smartCastCalculator.types(variable).any { KotlinTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) }) return if (smartCastCalculator.types(variable).any { KotlinTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) })
variable variable
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.idea.util.nullability
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.TypeNullability
@@ -43,7 +43,7 @@ class TypesWithContainsDetector(
private val heuristicSignatures = resolutionFacade.ideService<HeuristicSignatures>() private val heuristicSignatures = resolutionFacade.ideService<HeuristicSignatures>()
private val typesWithExtensionContains: Collection<KotlinType> = scope private val typesWithExtensionContains: Collection<KotlinType> = scope
.collectAllFromMeAndParent { it.getContributedFunctions(containsName, NoLookupLocation.FROM_IDE) } .collectFunctions(containsName, NoLookupLocation.FROM_IDE)
.filter { it.getExtensionReceiverParameter() != null && isGoodContainsFunction(it, listOf()) } .filter { it.getExtensionReceiverParameter() != null && isGoodContainsFunction(it, listOf()) }
.map { it.getExtensionReceiverParameter()!!.getType() } .map { it.getExtensionReceiverParameter()!!.getType() }
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
@@ -47,7 +47,7 @@ public class IterableTypesDetection(
private val cache = HashMap<FuzzyType, FuzzyType?>() private val cache = HashMap<FuzzyType, FuzzyType?>()
private val typesWithExtensionIterator: Collection<KotlinType> = scope private val typesWithExtensionIterator: Collection<KotlinType> = scope
.collectAllFromMeAndParent { it.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE) } .collectFunctions(iteratorName, NoLookupLocation.FROM_IDE)
.map { it.extensionReceiverParameter } .map { it.extensionReceiverParameter }
.filterNotNull() .filterNotNull()
.map { it.type } .map { it.type }
@@ -53,7 +53,8 @@ import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
@@ -230,14 +231,14 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<Kotlin
val name = originalFqName.shortName() val name = originalFqName.shortName()
if (refData.kind == KotlinReferenceData.Kind.EXTENSION_FUNCTION) { if (refData.kind == KotlinReferenceData.Kind.EXTENSION_FUNCTION) {
if (fileResolutionScope.parentsWithSelf.any { scope -> if (fileResolutionScope.findFunction(name, NoLookupLocation.FROM_IDE) { it.importableFqName == originalFqName } != null) {
scope.getContributedFunctions(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == originalFqName } return null // already imported
}) return null // already imported }
} }
else if (refData.kind == KotlinReferenceData.Kind.EXTENSION_PROPERTY) { else if (refData.kind == KotlinReferenceData.Kind.EXTENSION_PROPERTY) {
if (fileResolutionScope.parentsWithSelf.any { scope -> if (fileResolutionScope.findVariable(name, NoLookupLocation.FROM_IDE) { it.importableFqName == originalFqName } != null) {
scope.getContributedVariables(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == originalFqName } return null // already imported
}) return null // already imported }
} }
val referencedDescriptors = try { val referencedDescriptors = try {
@@ -119,19 +119,17 @@ public class KotlinImportOptimizer() : ImportOptimizer {
if (target.containingDeclaration !is ClassDescriptor) return false if (target.containingDeclaration !is ClassDescriptor) return false
fun isInScope(scope: LexicalScope): Boolean { fun isInScope(scope: LexicalScope): Boolean {
return scope.parentsWithSelf.any { return when (target) {
when (target) { is FunctionDescriptor ->
is FunctionDescriptor -> scope.findFunction(target.name, NoLookupLocation.FROM_IDE) { it == target } != null
it.getContributedFunctions(target.name, NoLookupLocation.FROM_IDE).contains(target)
is PropertyDescriptor -> is PropertyDescriptor ->
it.getContributedVariables(target.name, NoLookupLocation.FROM_IDE).contains(target) scope.findVariable(target.name, NoLookupLocation.FROM_IDE) { it == target } != null
is ClassDescriptor -> is ClassDescriptor ->
it.getContributedClassifier(target.name, NoLookupLocation.FROM_IDE) == target scope.findClassifier(target.name, NoLookupLocation.FROM_IDE) == target
else -> false else -> false
}
} }
} }
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.types.typeUtil.supertypes
@@ -124,8 +124,7 @@ public class ConvertFunctionToPropertyIntention : JetSelfTargetingIntention<KtNa
} }
callableDescriptor.getContainingScope() callableDescriptor.getContainingScope()
?.collectAllFromMeAndParent { it.getContributedVariables(callableDescriptor.name, NoLookupLocation.FROM_IDE) } ?.findVariable(callableDescriptor.name, NoLookupLocation.FROM_IDE)
?.firstOrNull()
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) } ?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } } ?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
} }
@@ -47,7 +47,7 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
import java.util.* import java.util.*
public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<KtProperty>(javaClass(), "Convert property to function"), LowPriorityAction { public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<KtProperty>(javaClass(), "Convert property to function"), LowPriorityAction {
@@ -103,8 +103,7 @@ public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<KtPr
if (callable is KtProperty) { if (callable is KtProperty) {
callableDescriptor.getContainingScope() callableDescriptor.getContainingScope()
?.collectAllFromMeAndParent { it.getContributedFunctions(callableDescriptor.name, NoLookupLocation.FROM_IDE) } ?.findFunction(callableDescriptor.name, NoLookupLocation.FROM_IDE) { it.valueParameters.isEmpty() }
?.firstOrNull { it.getValueParameters().isEmpty() }
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) } ?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } } ?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
} }
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
import java.util.* import java.util.*
public class JetChangeSignatureData( public class JetChangeSignatureData(
@@ -80,9 +80,8 @@ public class JetChangeSignatureData(
val bodyScope = (callable as? KtFunction)?.bodyExpression?.let { it.getResolutionScope(it.analyze(), it.getResolutionFacade()) } val bodyScope = (callable as? KtFunction)?.bodyExpression?.let { it.getResolutionScope(it.analyze(), it.getResolutionFacade()) }
val paramNames = baseDescriptor.valueParameters.map { it.name.asString() } val paramNames = baseDescriptor.valueParameters.map { it.name.asString() }
val validator = bodyScope?.let { bodyScope -> val validator = bodyScope?.let { bodyScope ->
CollectingNameValidator(paramNames) { name -> CollectingNameValidator(paramNames) {
val identifier = Name.identifier(name) bodyScope.findVariable(Name.identifier(it), NoLookupLocation.FROM_IDE) == null
bodyScope.collectAllFromMeAndParent { it.getContributedVariables(identifier, NoLookupLocation.FROM_IDE) }.isEmpty()
} }
} ?: CollectingNameValidator(paramNames) } ?: CollectingNameValidator(paramNames)
val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null
@@ -43,8 +43,9 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
import org.jetbrains.kotlin.resolve.scopes.utils.findPackage import org.jetbrains.kotlin.resolve.scopes.utils.findPackage
import org.jetbrains.kotlin.resolve.scopes.utils.processForMeAndParent import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.* import java.util.*
@@ -108,29 +109,20 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
private fun isAlreadyImported(target: DeclarationDescriptor, topLevelScope: LexicalScope, targetFqName: FqName): Boolean { private fun isAlreadyImported(target: DeclarationDescriptor, topLevelScope: LexicalScope, targetFqName: FqName): Boolean {
val name = target.name val name = target.name
when (target) { return when (target) {
is ClassDescriptor -> { is ClassDescriptor -> {
val classifier = topLevelScope.findClassifier(name, NoLookupLocation.FROM_IDE) val classifier = topLevelScope.findClassifier(name, NoLookupLocation.FROM_IDE)
if (classifier?.importableFqName == targetFqName) return true classifier?.importableFqName == targetFqName
} }
is FunctionDescriptor -> { is FunctionDescriptor ->
topLevelScope.processForMeAndParent { topLevelScope.findFunction(name, NoLookupLocation.FROM_IDE) { it.importableFqName == targetFqName } != null
if (it.getContributedFunctions(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == targetFqName }) {
return true
}
}
}
is PropertyDescriptor -> { is PropertyDescriptor ->
topLevelScope.processForMeAndParent { topLevelScope.findVariable(name, NoLookupLocation.FROM_IDE) { it.importableFqName == targetFqName } != null
if (it.getContributedVariables(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == targetFqName }) {
return true else -> false
}
}
}
} }
return false
} }
fun importDescriptor(descriptor: DeclarationDescriptor): ImportDescriptorResult { fun importDescriptor(descriptor: DeclarationDescriptor): ImportDescriptorResult {