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?
= 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.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<FunctionDescriptor> {
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)
@@ -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<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> {
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 {
@@ -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
@@ -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<HeuristicSignatures>()
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()) }
.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.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<FuzzyType, FuzzyType?>()
private val typesWithExtensionIterator: Collection<KotlinType> = scope
.collectAllFromMeAndParent { it.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE) }
.collectFunctions(iteratorName, NoLookupLocation.FROM_IDE)
.map { it.extensionReceiverParameter }
.filterNotNull()
.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.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<Kotlin
val name = originalFqName.shortName()
if (refData.kind == KotlinReferenceData.Kind.EXTENSION_FUNCTION) {
if (fileResolutionScope.parentsWithSelf.any { scope ->
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 {
@@ -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
}
}
@@ -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<KtNa
}
callableDescriptor.getContainingScope()
?.collectAllFromMeAndParent { it.getContributedVariables(callableDescriptor.name, NoLookupLocation.FROM_IDE) }
?.firstOrNull()
?.findVariable(callableDescriptor.name, NoLookupLocation.FROM_IDE)
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
?.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.calls.callUtil.getCall
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.*
public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<KtProperty>(javaClass(), "Convert property to function"), LowPriorityAction {
@@ -103,8 +103,7 @@ public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<KtPr
if (callable is KtProperty) {
callableDescriptor.getContainingScope()
?.collectAllFromMeAndParent { it.getContributedFunctions(callableDescriptor.name, NoLookupLocation.FROM_IDE) }
?.firstOrNull { it.getValueParameters().isEmpty() }
?.findFunction(callableDescriptor.name, NoLookupLocation.FROM_IDE) { it.valueParameters.isEmpty() }
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
?.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.KtNamedDeclaration
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.*
public class JetChangeSignatureData(
@@ -80,9 +80,8 @@ public class JetChangeSignatureData(
val bodyScope = (callable as? KtFunction)?.bodyExpression?.let { it.getResolutionScope(it.analyze(), it.getResolutionFacade()) }
val paramNames = baseDescriptor.valueParameters.map { it.name.asString() }
val validator = bodyScope?.let { bodyScope ->
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
@@ -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 {