From c09cf634241823d36665ab1985c085eb63994efd Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Sun, 25 Oct 2015 12:26:50 +0300 Subject: [PATCH] Added utility functions for functions and variables in scope --- .../kotlin/resolve/scopes/utils/ScopeUtils.kt | 25 +++++++++++++++-- .../jetbrains/kotlin/idea/util/scopeUtils.kt | 7 +++-- .../smart/MultipleArgumentsItemProvider.kt | 7 ++--- .../smart/TypesWithContainsDetector.kt | 4 +-- .../idea/core/IterableTypesDetection.kt | 4 +-- .../KotlinCopyPasteReferenceProcessor.kt | 15 +++++----- .../idea/imports/KotlinImportOptimizer.kt | 18 ++++++------ .../ConvertFunctionToPropertyIntention.kt | 5 ++-- .../ConvertPropertyToFunctionIntention.kt | 5 ++-- .../changeSignature/JetChangeSignatureData.kt | 7 ++--- .../idea/util/ImportInsertHelperImpl.kt | 28 +++++++------------ 11 files changed, 66 insertions(+), 59 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt index cceb159d1b3..ffe6b3473dc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt @@ -97,6 +97,26 @@ public fun LexicalScope.findClassifier(name: Name, location: LookupLocation): Cl public fun LexicalScope.findPackage(name: Name): PackageViewDescriptor? = findFirstFromImportingScopes { it.getContributedPackage(name) } +public fun LexicalScope.collectVariables(name: Name, location: LookupLocation): Collection + = collectAllFromMeAndParent { it.getContributedVariables(name, location) } + +public fun LexicalScope.collectFunctions(name: Name, location: LookupLocation): Collection + = 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.asKtScope(): KtScope { @@ -128,9 +148,8 @@ private class LexicalToKtScopeAdapter(lexicalScope: LexicalScope): KtScope { return lexicalScope.collectAllFromImportingScopes { it.getContributedVariables(name, location) } } - override fun getFunctions(name: Name, location: LookupLocation): Collection { - return lexicalScope.collectAllFromMeAndParent { it.getContributedFunctions(name, location) } - } + override fun getFunctions(name: Name, location: LookupLocation) + = lexicalScope.collectFunctions(name, location) override fun getLocalVariable(name: Name) = lexicalScope.findLocalVariable(name) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt index 8c4479fb53e..ad2454a52fe 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt @@ -23,16 +23,17 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name 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 { - 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 { 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 = getImplicitReceiversWithInstance().flatMap { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt index 492b4c24ac5..667c6f6d1fa 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/MultipleArgumentsItemProvider.kt @@ -36,9 +36,9 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.BindingContext 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.utils.collectAllFromMeAndParent -import org.jetbrains.kotlin.resolve.scopes.utils.findLocalVariable +import org.jetbrains.kotlin.resolve.scopes.utils.findVariable import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import java.util.* @@ -106,8 +106,7 @@ class MultipleArgumentsItemProvider( private fun variableInScope(parameter: ValueParameterDescriptor, scope: LexicalScope): VariableDescriptor? { 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) - val variable = scope.findLocalVariable(name) - ?: scope.collectAllFromMeAndParent { it.getContributedVariables(name, NoLookupLocation.FROM_IDE) }.singleOrNull() + val variable = scope.findVariable(name, NoLookupLocation.FROM_IDE) { !it.isExtension } ?: scope.getVariableFromImplicitReceivers(name) ?: return null return if (smartCastCalculator.types(variable).any { KotlinTypeChecker.DEFAULT.isSubtypeOf(it, parameter.getType()) }) variable diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypesWithContainsDetector.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypesWithContainsDetector.kt index 3ef71cb7f5e..d6933667e24 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypesWithContainsDetector.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypesWithContainsDetector.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.idea.util.nullability import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name 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.TypeUtils import org.jetbrains.kotlin.types.typeUtil.TypeNullability @@ -43,7 +43,7 @@ class TypesWithContainsDetector( private val heuristicSignatures = resolutionFacade.ideService() private val typesWithExtensionContains: Collection = scope - .collectAllFromMeAndParent { it.getContributedFunctions(containsName, NoLookupLocation.FROM_IDE) } + .collectFunctions(containsName, NoLookupLocation.FROM_IDE) .filter { it.getExtensionReceiverParameter() != null && isGoodContainsFunction(it, listOf()) } .map { it.getExtensionReceiverParameter()!!.getType() } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt index 8e682bf2c27..709176d28d1 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.scopes.LexicalScope 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.TypeUtils import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext @@ -47,7 +47,7 @@ public class IterableTypesDetection( private val cache = HashMap() private val typesWithExtensionIterator: Collection = scope - .collectAllFromMeAndParent { it.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE) } + .collectFunctions(iteratorName, NoLookupLocation.FROM_IDE) .map { it.extensionReceiverParameter } .filterNotNull() .map { it.type } diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinCopyPasteReferenceProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinCopyPasteReferenceProcessor.kt index fffb64c7ff2..7e54c5e0d97 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinCopyPasteReferenceProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinCopyPasteReferenceProcessor.kt @@ -53,7 +53,8 @@ import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.DescriptorUtils 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.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -230,14 +231,14 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor - scope.getContributedFunctions(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == originalFqName } - }) return null // already imported + if (fileResolutionScope.findFunction(name, NoLookupLocation.FROM_IDE) { it.importableFqName == originalFqName } != null) { + return null // already imported + } } else if (refData.kind == KotlinReferenceData.Kind.EXTENSION_PROPERTY) { - if (fileResolutionScope.parentsWithSelf.any { scope -> - scope.getContributedVariables(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == originalFqName } - }) return null // already imported + if (fileResolutionScope.findVariable(name, NoLookupLocation.FROM_IDE) { it.importableFqName == originalFqName } != null) { + return null // already imported + } } val referencedDescriptors = try { diff --git a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt index 3547b77758c..166de1c3f01 100644 --- a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt @@ -119,19 +119,17 @@ public class KotlinImportOptimizer() : ImportOptimizer { if (target.containingDeclaration !is ClassDescriptor) return false fun isInScope(scope: LexicalScope): Boolean { - return scope.parentsWithSelf.any { - when (target) { - is FunctionDescriptor -> - it.getContributedFunctions(target.name, NoLookupLocation.FROM_IDE).contains(target) + return when (target) { + is FunctionDescriptor -> + scope.findFunction(target.name, NoLookupLocation.FROM_IDE) { it == target } != null - is PropertyDescriptor -> - it.getContributedVariables(target.name, NoLookupLocation.FROM_IDE).contains(target) + is PropertyDescriptor -> + scope.findVariable(target.name, NoLookupLocation.FROM_IDE) { it == target } != null - is ClassDescriptor -> - it.getContributedClassifier(target.name, NoLookupLocation.FROM_IDE) == target + is ClassDescriptor -> + scope.findClassifier(target.name, NoLookupLocation.FROM_IDE) == target - else -> false - } + else -> false } } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt index fa867abd4fa..e277921b8d6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt @@ -50,7 +50,7 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns 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.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.supertypes @@ -124,8 +124,7 @@ public class ConvertFunctionToPropertyIntention : JetSelfTargetingIntention(javaClass(), "Convert property to function"), LowPriorityAction { @@ -103,8 +103,7 @@ public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention - CollectingNameValidator(paramNames) { name -> - val identifier = Name.identifier(name) - bodyScope.collectAllFromMeAndParent { it.getContributedVariables(identifier, NoLookupLocation.FROM_IDE) }.isEmpty() + CollectingNameValidator(paramNames) { + bodyScope.findVariable(Name.identifier(it), NoLookupLocation.FROM_IDE) == null } } ?: CollectingNameValidator(paramNames) val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt index ca8fbbe204a..f64d9fda0ca 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt @@ -43,8 +43,9 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue 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.processForMeAndParent +import org.jetbrains.kotlin.resolve.scopes.utils.findVariable import org.jetbrains.kotlin.utils.addIfNotNull 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 { val name = target.name - when (target) { + return when (target) { is ClassDescriptor -> { val classifier = topLevelScope.findClassifier(name, NoLookupLocation.FROM_IDE) - if (classifier?.importableFqName == targetFqName) return true + classifier?.importableFqName == targetFqName } - is FunctionDescriptor -> { - topLevelScope.processForMeAndParent { - if (it.getContributedFunctions(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == targetFqName }) { - return true - } - } - } + is FunctionDescriptor -> + topLevelScope.findFunction(name, NoLookupLocation.FROM_IDE) { it.importableFqName == targetFqName } != null - is PropertyDescriptor -> { - topLevelScope.processForMeAndParent { - if (it.getContributedVariables(name, NoLookupLocation.FROM_IDE).any { it.importableFqName == targetFqName }) { - return true - } - } - } + is PropertyDescriptor -> + topLevelScope.findVariable(name, NoLookupLocation.FROM_IDE) { it.importableFqName == targetFqName } != null + + else -> false } - return false } fun importDescriptor(descriptor: DeclarationDescriptor): ImportDescriptorResult {