1/2 Preparation commit: move ide-common files which are required for scripting to separate directory

This commit is needed to preserve git history
This commit is contained in:
Nikita Bobko
2021-07-02 16:22:11 +02:00
parent 50797dba8d
commit cf3f35e1c8
16 changed files with 0 additions and 33 deletions

View File

@@ -0,0 +1,494 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.load.kotlin.toSourceElement
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent
import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.synthetic.JavaSyntheticScopes
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
import org.jetbrains.kotlin.types.typeUtil.isUnit
import java.util.*
@OptIn(FrontendInternals::class)
class ReferenceVariantsHelper(
private val bindingContext: BindingContext,
private val resolutionFacade: ResolutionFacade,
private val moduleDescriptor: ModuleDescriptor,
private val visibilityFilter: (DeclarationDescriptor) -> Boolean,
private val notProperties: Set<FqNameUnsafe> = setOf()
) {
fun getReferenceVariants(
expression: KtSimpleNameExpression,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = true,
filterOutShadowed: Boolean = true,
excludeNonInitializedVariable: Boolean = true,
useReceiverType: KotlinType? = null
): Collection<DeclarationDescriptor> = getReferenceVariants(
expression, CallTypeAndReceiver.detect(expression),
kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, excludeNonInitializedVariable, useReceiverType
)
fun getReferenceVariants(
contextElement: PsiElement,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
filterOutJavaGettersAndSetters: Boolean = true,
filterOutShadowed: Boolean = true,
excludeNonInitializedVariable: Boolean = true,
useReceiverType: KotlinType? = null
): Collection<DeclarationDescriptor> {
var variants: Collection<DeclarationDescriptor> =
getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useReceiverType)
.filter { !resolutionFacade.frontendService<DeprecationResolver>().isHiddenInResolution(it) && visibilityFilter(it) }
if (filterOutShadowed) {
ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, contextElement, callTypeAndReceiver)?.let {
variants = it.filter(variants)
}
}
if (filterOutJavaGettersAndSetters && kindFilter.kindMask.and(DescriptorKindFilter.FUNCTIONS_MASK) != 0) {
variants = filterOutJavaGettersAndSetters(variants)
}
if (excludeNonInitializedVariable && kindFilter.kindMask.and(DescriptorKindFilter.VARIABLES_MASK) != 0) {
variants = excludeNonInitializedVariable(variants, contextElement)
}
return variants
}
fun <TDescriptor : DeclarationDescriptor> filterOutJavaGettersAndSetters(variants: Collection<TDescriptor>): Collection<TDescriptor> {
val accessorMethodsToRemove = HashSet<FunctionDescriptor>()
val filteredVariants = variants.filter { it !is SyntheticJavaPropertyDescriptor || !it.suppressedByNotPropertyList(notProperties) }
for (variant in filteredVariants) {
if (variant is SyntheticJavaPropertyDescriptor) {
accessorMethodsToRemove.add(variant.getMethod.original)
val setter = variant.setMethod
if (setter != null && setter.returnType?.isUnit() == true) { // we do not filter out non-Unit setters
accessorMethodsToRemove.add(setter.original)
}
}
}
return filteredVariants.filter { it !is FunctionDescriptor || it.original !in accessorMethodsToRemove }
}
// filters out variable inside its initializer
fun excludeNonInitializedVariable(
variants: Collection<DeclarationDescriptor>,
contextElement: PsiElement
): Collection<DeclarationDescriptor> {
for (element in contextElement.parentsWithSelf) {
val parent = element.parent
if (parent is KtVariableDeclaration && element == parent.initializer) {
return variants.filter { it.findPsi() != parent }
}
if (element is KtDeclaration) break // we can use variable inside lambda or anonymous object located in its initializer
}
return variants
}
private fun getReferenceVariantsNoVisibilityFilter(
contextElement: PsiElement,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
useReceiverType: KotlinType?
): Collection<DeclarationDescriptor> {
val callType = callTypeAndReceiver.callType
@Suppress("NAME_SHADOWING")
val kindFilter = kindFilter.intersect(callType.descriptorKindFilter)
val receiverExpression: KtExpression?
when (callTypeAndReceiver) {
is CallTypeAndReceiver.IMPORT_DIRECTIVE -> {
return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter)
}
is CallTypeAndReceiver.PACKAGE_DIRECTIVE -> {
return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter)
}
is CallTypeAndReceiver.TYPE -> {
return getVariantsForUserType(callTypeAndReceiver.receiver, contextElement, kindFilter, nameFilter)
}
is CallTypeAndReceiver.ANNOTATION -> {
return getVariantsForUserType(callTypeAndReceiver.receiver, contextElement, kindFilter, nameFilter)
}
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
return getVariantsForCallableReference(callTypeAndReceiver, contextElement, useReceiverType, kindFilter, nameFilter)
}
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver
is CallTypeAndReceiver.SUPER_MEMBERS -> receiverExpression = callTypeAndReceiver.receiver
is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver
is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver
is CallTypeAndReceiver.OPERATOR -> return emptyList()
is CallTypeAndReceiver.UNKNOWN -> return emptyList()
else -> throw RuntimeException() //TODO: see KT-9394
}
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(contextElement)
val containingDeclaration = resolutionScope.ownerDescriptor
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance(
languageVersionSettings.supportsFeature(LanguageFeature.DslMarkersSupport)
).flatMap {
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
it.value,
bindingContext,
containingDeclaration,
dataFlowInfo,
languageVersionSettings,
resolutionFacade.frontendService<DataFlowValueFactory>()
)
}.toSet()
val descriptors = LinkedHashSet<DeclarationDescriptor>()
val filterWithoutExtensions = kindFilter exclude DescriptorKindExclude.Extensions
if (receiverExpression != null) {
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression]
if (qualifier != null) {
descriptors.addAll(qualifier.staticScope.collectStaticMembers(resolutionFacade, filterWithoutExtensions, nameFilter))
}
val explicitReceiverTypes = if (useReceiverType != null) {
listOf(useReceiverType)
} else {
callTypeAndReceiver.receiverTypes(
bindingContext,
contextElement,
moduleDescriptor,
resolutionFacade,
stableSmartCastsOnly = false
)!!
}
descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter)
} else {
assert(useReceiverType == null) { "'useReceiverType' parameter is not supported for implicit receiver" }
descriptors.processAll(implicitReceiverTypes, implicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter)
// add non-instance members
descriptors.addAll(
resolutionScope.collectDescriptorsFiltered(
filterWithoutExtensions,
nameFilter,
changeNamesForAliased = true
)
)
descriptors.addAll(resolutionScope.collectAllFromMeAndParent { scope ->
scope.collectSyntheticStaticMembersAndConstructors(resolutionFacade, kindFilter, nameFilter)
})
}
if (callType == CallType.SUPER_MEMBERS) { // we need to unwrap fake overrides in case of "super." because ShadowedDeclarationsFilter does not work correctly
return descriptors.flatMapTo(LinkedHashSet<DeclarationDescriptor>()) {
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
it.overriddenDescriptors
else
listOf(it)
}
}
return descriptors
}
private fun getVariantsForUserType(
receiverExpression: KtExpression?,
contextElement: PsiElement,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
if (receiverExpression != null) {
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
return qualifier.staticScope.collectStaticMembers(resolutionFacade, kindFilter, nameFilter)
} else {
val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
return scope.collectDescriptorsFiltered(kindFilter, nameFilter, changeNamesForAliased = true)
}
}
private fun getVariantsForCallableReference(
callTypeAndReceiver: CallTypeAndReceiver.CALLABLE_REFERENCE,
contextElement: PsiElement,
useReceiverType: KotlinType?,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
val descriptors = LinkedHashSet<DeclarationDescriptor>()
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
val receiver = callTypeAndReceiver.receiver
if (receiver != null) {
val isStatic = bindingContext[BindingContext.DOUBLE_COLON_LHS, receiver] is DoubleColonLHS.Type
val explicitReceiverTypes = if (useReceiverType != null) {
listOf(useReceiverType)
} else {
callTypeAndReceiver.receiverTypes(
bindingContext,
contextElement,
moduleDescriptor,
resolutionFacade,
stableSmartCastsOnly = false
)!!
}
val constructorFilter = { descriptor: ClassDescriptor -> if (isStatic) true else descriptor.isInner }
descriptors.addNonExtensionMembers(explicitReceiverTypes, kindFilter, nameFilter, constructorFilter)
descriptors.addScopeAndSyntheticExtensions(
resolutionScope,
explicitReceiverTypes,
CallType.CALLABLE_REFERENCE,
kindFilter,
nameFilter
)
if (isStatic) {
explicitReceiverTypes
.mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope }
.flatMapTo(descriptors) { it.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) }
}
} else {
// process non-instance members and class constructors
descriptors.addNonExtensionCallablesAndConstructors(
resolutionScope,
kindFilter, nameFilter, constructorFilter = { !it.isInner },
classesOnly = false
)
}
return descriptors
}
private fun getVariantsForImportOrPackageDirective(
receiverExpression: KtExpression?,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
if (receiverExpression != null) {
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
val staticDescriptors = qualifier.staticScope.collectStaticMembers(resolutionFacade, kindFilter, nameFilter)
val objectDescriptor =
(qualifier as? ClassQualifier)?.descriptor?.takeIf { it.kind == ClassKind.OBJECT } ?: return staticDescriptors
return staticDescriptors + objectDescriptor.defaultType.memberScope.getDescriptorsFiltered(kindFilter, nameFilter)
} else {
val rootPackage = resolutionFacade.moduleDescriptor.getPackage(FqName.ROOT)
return rootPackage.memberScope.getDescriptorsFiltered(kindFilter, nameFilter)
}
}
private fun MutableSet<DeclarationDescriptor>.processAll(
implicitReceiverTypes: Collection<KotlinType>,
receiverTypes: Collection<KotlinType>,
resolutionScope: LexicalScope,
callType: CallType<*>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
) {
addNonExtensionMembers(receiverTypes, kindFilter, nameFilter, constructorFilter = { it.isInner })
addMemberExtensions(implicitReceiverTypes, receiverTypes, callType, kindFilter, nameFilter)
addScopeAndSyntheticExtensions(resolutionScope, receiverTypes, callType, kindFilter, nameFilter)
}
private fun MutableSet<DeclarationDescriptor>.addMemberExtensions(
dispatchReceiverTypes: Collection<KotlinType>,
extensionReceiverTypes: Collection<KotlinType>,
callType: CallType<*>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
) {
val memberFilter = kindFilter exclude DescriptorKindExclude.NonExtensions
for (dispatchReceiverType in dispatchReceiverTypes) {
for (member in dispatchReceiverType.memberScope.getDescriptorsFiltered(memberFilter, nameFilter)) {
addAll((member as CallableDescriptor).substituteExtensionIfCallable(extensionReceiverTypes, callType))
}
}
}
private fun MutableSet<DeclarationDescriptor>.addNonExtensionMembers(
receiverTypes: Collection<KotlinType>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
constructorFilter: (ClassDescriptor) -> Boolean
) {
for (receiverType in receiverTypes) {
addNonExtensionCallablesAndConstructors(
receiverType.memberScope.memberScopeAsImportingScope(),
kindFilter, nameFilter, constructorFilter,
false
)
receiverType.constructor.supertypes.forEach {
addNonExtensionCallablesAndConstructors(
it.memberScope.memberScopeAsImportingScope(),
kindFilter, nameFilter, constructorFilter,
true
)
}
}
}
private fun MutableSet<DeclarationDescriptor>.addNonExtensionCallablesAndConstructors(
scope: HierarchicalScope,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
constructorFilter: (ClassDescriptor) -> Boolean,
classesOnly: Boolean
) {
var filterToUse =
DescriptorKindFilter(kindFilter.kindMask and DescriptorKindFilter.CALLABLES.kindMask).exclude(DescriptorKindExclude.Extensions)
// should process classes if we need constructors
if (filterToUse.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) {
filterToUse = filterToUse.withKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK)
}
for (descriptor in scope.collectDescriptorsFiltered(filterToUse, nameFilter, changeNamesForAliased = true)) {
if (descriptor is ClassDescriptor) {
if (descriptor.modality == Modality.ABSTRACT || descriptor.modality == Modality.SEALED) continue
if (!constructorFilter(descriptor)) continue
descriptor.constructors.filterTo(this) { kindFilter.accepts(it) }
} else if (!classesOnly && kindFilter.accepts(descriptor)) {
this.add(descriptor)
}
}
}
private fun MutableSet<DeclarationDescriptor>.addScopeAndSyntheticExtensions(
scope: LexicalScope,
receiverTypes: Collection<KotlinType>,
callType: CallType<*>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
) {
if (kindFilter.excludes.contains(DescriptorKindExclude.Extensions)) return
if (receiverTypes.isEmpty()) return
fun process(extensionOrSyntheticMember: CallableDescriptor) {
if (kindFilter.accepts(extensionOrSyntheticMember) && nameFilter(extensionOrSyntheticMember.name)) {
if (extensionOrSyntheticMember.isExtension) {
addAll(extensionOrSyntheticMember.substituteExtensionIfCallable(receiverTypes, callType))
} else {
add(extensionOrSyntheticMember)
}
}
}
for (descriptor in scope.collectDescriptorsFiltered(
kindFilter exclude DescriptorKindExclude.NonExtensions,
nameFilter,
changeNamesForAliased = true
)) {
// todo: sometimes resolution scope here is LazyJavaClassMemberScope. see ea.jetbrains.com/browser/ea_problems/72572
process(descriptor as CallableDescriptor)
}
val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java).forceEnableSamAdapters()
if (kindFilter.acceptsKinds(DescriptorKindFilter.VARIABLES_MASK)) {
val lookupLocation = (scope.ownerDescriptor.toSourceElement.getPsi() as? KtElement)?.let { KotlinLookupLocation(it) }
?: NoLookupLocation.FROM_IDE
for (extension in syntheticScopes.collectSyntheticExtensionProperties(receiverTypes, lookupLocation)) {
process(extension)
}
}
if (kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) {
for (syntheticMember in syntheticScopes.collectSyntheticMemberFunctions(receiverTypes)) {
process(syntheticMember)
}
}
}
}
private fun MemberScope.collectStaticMembers(
resolutionFacade: ResolutionFacade,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> {
return getDescriptorsFiltered(kindFilter, nameFilter) + collectSyntheticStaticMembersAndConstructors(
resolutionFacade,
kindFilter,
nameFilter
)
}
@OptIn(FrontendInternals::class)
fun ResolutionScope.collectSyntheticStaticMembersAndConstructors(
resolutionFacade: ResolutionFacade,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
): List<FunctionDescriptor> {
val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java)
val functionDescriptors = getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
val classifierDescriptors = getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
return (syntheticScopes.forceEnableSamAdapters().collectSyntheticStaticFunctions(functionDescriptors) +
syntheticScopes.collectSyntheticConstructors(classifierDescriptors))
.filter { kindFilter.accepts(it) && nameFilter(it.name) }
}
// New Inference disables scope with synthetic SAM-adapters because it uses conversions for resolution
// However, sometimes we need to pretend that we have those synthetic members, for example:
// - to show both option (with SAM-conversion signature, and without) in completion
// - for various intentions and checks (see RedundantSamConstructorInspection, ConflictingExtensionPropertyIntention and other)
// TODO(dsavvinov): review clients, rewrite them to not rely on synthetic adapetrs
fun SyntheticScopes.forceEnableSamAdapters(): SyntheticScopes {
return if (this !is JavaSyntheticScopes)
this
else
object : SyntheticScopes {
override val scopes: Collection<SyntheticScope> = this@forceEnableSamAdapters.scopesWithForceEnabledSamAdapters
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.resolve
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.ResolverForProject
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
interface ResolutionFacade {
val project: Project
fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext
fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext
fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>, callback: DiagnosticSink.DiagnosticsCallback? = null): AnalysisResult
fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): DeclarationDescriptor
val moduleDescriptor: ModuleDescriptor
// get service for the module this resolution was created for
@FrontendInternals
fun <T : Any> getFrontendService(serviceClass: Class<T>): T
fun <T : Any> getIdeService(serviceClass: Class<T>): T
// get service for the module defined by PsiElement/ModuleDescriptor passed as parameter
@FrontendInternals
fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T
@FrontendInternals
fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T?
@FrontendInternals
fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
fun getResolverForProject(): ResolverForProject<out ModuleInfo>
}
@FrontendInternals
inline fun <reified T : Any> ResolutionFacade.frontendService(): T = this.getFrontendService(T::class.java)
inline fun <reified T : Any> ResolutionFacade.ideService(): T = this.getIdeService(T::class.java)

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.resolve
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
/**
* Helper methods for commonly used frontend components.
* Use them to avoid explicit opt-ins.
* Before adding a new helper method please make sure component doesn't have fragile invariants that can be violated by external use.
*/
@OptIn(FrontendInternals::class)
fun ResolutionFacade.getLanguageVersionSettings(): LanguageVersionSettings =
frontendService<LanguageVersionSettings>()
@OptIn(FrontendInternals::class)
fun ResolutionFacade.getDataFlowValueFactory(): DataFlowValueFactory =
frontendService<DataFlowValueFactory>()

View File

@@ -0,0 +1,376 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.resolve.getDataFlowValueFactory
import org.jetbrains.kotlin.idea.resolve.getLanguageVersionSettings
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.TypeAliasQualifier
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
import org.jetbrains.kotlin.util.supertypesWithAny
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.util.*
sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
object UNKNOWN : CallType<Nothing?>(DescriptorKindFilter.ALL)
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
object DOT : CallType<KtExpression>(DescriptorKindFilter.ALL)
object SAFE : CallType<KtExpression>(DescriptorKindFilter.ALL)
object SUPER_MEMBERS : CallType<KtSuperExpression>(
DescriptorKindFilter.CALLABLES exclude DescriptorKindExclude.Extensions exclude AbstractMembersExclude
)
object INFIX : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonInfixExclude)
object OPERATOR : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonOperatorExclude)
object CALLABLE_REFERENCE : CallType<KtExpression?>(DescriptorKindFilter.CALLABLES exclude CallableReferenceExclude)
object IMPORT_DIRECTIVE : CallType<KtExpression?>(DescriptorKindFilter.ALL)
object PACKAGE_DIRECTIVE : CallType<KtExpression?>(DescriptorKindFilter.PACKAGES)
object TYPE : CallType<KtExpression?>(
DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK)
exclude DescriptorKindExclude.EnumEntry
)
object DELEGATE : CallType<KtExpression?>(DescriptorKindFilter.FUNCTIONS exclude NonOperatorExclude)
object ANNOTATION : CallType<KtExpression?>(
DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK)
exclude NonAnnotationClassifierExclude
)
private object NonInfixExclude : DescriptorKindExclude() {
override fun excludes(descriptor: DeclarationDescriptor) =
!(descriptor is SimpleFunctionDescriptor && descriptor.isInfix)
override val fullyExcludedDescriptorKinds: Int
get() = 0
}
private object NonOperatorExclude : DescriptorKindExclude() {
override fun excludes(descriptor: DeclarationDescriptor) =
!(descriptor is SimpleFunctionDescriptor && descriptor.isOperator)
override val fullyExcludedDescriptorKinds: Int
get() = 0
}
private object CallableReferenceExclude : DescriptorKindExclude() {
override fun excludes(descriptor: DeclarationDescriptor) /* currently not supported for locals and synthetic */ =
descriptor !is CallableMemberDescriptor || descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
override val fullyExcludedDescriptorKinds: Int
get() = 0
}
private object NonAnnotationClassifierExclude : DescriptorKindExclude() {
override fun excludes(descriptor: DeclarationDescriptor): Boolean {
if (descriptor !is ClassifierDescriptor) return false
return descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS
}
override val fullyExcludedDescriptorKinds: Int get() = 0
}
private object AbstractMembersExclude : DescriptorKindExclude() {
override fun excludes(descriptor: DeclarationDescriptor) =
descriptor is CallableMemberDescriptor && descriptor.modality == Modality.ABSTRACT
override val fullyExcludedDescriptorKinds: Int
get() = 0
}
}
sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallType<TReceiver>>(
val callType: TCallType,
val receiver: TReceiver
) {
object UNKNOWN : CallTypeAndReceiver<Nothing?, CallType.UNKNOWN>(CallType.UNKNOWN, null)
object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>(CallType.DEFAULT, null)
class DOT(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.DOT>(CallType.DOT, receiver)
class SAFE(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.SAFE>(CallType.SAFE, receiver)
class SUPER_MEMBERS(receiver: KtSuperExpression) : CallTypeAndReceiver<KtSuperExpression, CallType.SUPER_MEMBERS>(
CallType.SUPER_MEMBERS, receiver
)
class INFIX(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.INFIX>(CallType.INFIX, receiver)
class OPERATOR(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.OPERATOR>(CallType.OPERATOR, receiver)
class CALLABLE_REFERENCE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.CALLABLE_REFERENCE>(
CallType.CALLABLE_REFERENCE, receiver
)
class IMPORT_DIRECTIVE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.IMPORT_DIRECTIVE>(
CallType.IMPORT_DIRECTIVE, receiver
)
class PACKAGE_DIRECTIVE(receiver: KtExpression?) :
CallTypeAndReceiver<KtExpression?, CallType.PACKAGE_DIRECTIVE>(CallType.PACKAGE_DIRECTIVE, receiver)
class TYPE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.TYPE>(CallType.TYPE, receiver)
class DELEGATE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.DELEGATE>(CallType.DELEGATE, receiver)
class ANNOTATION(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.ANNOTATION>(CallType.ANNOTATION, receiver)
companion object {
fun detect(expression: KtSimpleNameExpression): CallTypeAndReceiver<*, *> {
val parent = expression.parent
if (parent is KtCallableReferenceExpression && expression == parent.callableReference) {
return CALLABLE_REFERENCE(parent.receiverExpression)
}
val receiverExpression = expression.getReceiverExpression()
if (expression.isImportDirectiveExpression()) {
return IMPORT_DIRECTIVE(receiverExpression)
}
if (expression.isPackageDirectiveExpression()) {
return PACKAGE_DIRECTIVE(receiverExpression)
}
if (parent is KtUserType) {
val constructorCallee = (parent.parent as? KtTypeReference)?.parent as? KtConstructorCalleeExpression
if (constructorCallee != null && constructorCallee.parent is KtAnnotationEntry) {
return ANNOTATION(receiverExpression)
}
return TYPE(receiverExpression)
}
when (expression) {
is KtOperationReferenceExpression -> {
if (receiverExpression == null) {
return UNKNOWN // incomplete code
}
return when (parent) {
is KtBinaryExpression -> {
if (parent.operationToken == KtTokens.IDENTIFIER)
INFIX(receiverExpression)
else
OPERATOR(receiverExpression)
}
is KtUnaryExpression -> OPERATOR(receiverExpression)
else -> error("Unknown parent for JetOperationReferenceExpression: $parent with text '${parent.text}'")
}
}
is KtNameReferenceExpression -> {
if (receiverExpression == null) {
return DEFAULT
}
if (receiverExpression is KtSuperExpression) {
return SUPER_MEMBERS(receiverExpression)
}
return when (parent) {
is KtCallExpression -> {
if ((parent.parent as KtQualifiedExpression).operationSign == KtTokens.SAFE_ACCESS)
SAFE(receiverExpression)
else
DOT(receiverExpression)
}
is KtQualifiedExpression -> {
if (parent.operationSign == KtTokens.SAFE_ACCESS)
SAFE(receiverExpression)
else
DOT(receiverExpression)
}
else -> error("Unknown parent for JetNameReferenceExpression with receiver: $parent")
}
}
else -> return UNKNOWN
}
}
}
}
data class ReceiverType(
val type: KotlinType,
val receiverIndex: Int,
val implicitValue: ReceiverValue? = null
) {
val implicit: Boolean get() = implicitValue != null
fun extractDslMarkers() =
implicitValue?.let(DslMarkerUtils::extractDslMarkerFqNames)?.all()
?: DslMarkerUtils.extractDslMarkerFqNames(type)
}
fun CallTypeAndReceiver<*, *>.receiverTypes(
bindingContext: BindingContext,
contextElement: PsiElement,
moduleDescriptor: ModuleDescriptor,
resolutionFacade: ResolutionFacade,
stableSmartCastsOnly: Boolean
): List<KotlinType>? {
return receiverTypesWithIndex(bindingContext, contextElement, moduleDescriptor, resolutionFacade, stableSmartCastsOnly)?.map { it.type }
}
fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
bindingContext: BindingContext,
contextElement: PsiElement,
moduleDescriptor: ModuleDescriptor,
resolutionFacade: ResolutionFacade,
stableSmartCastsOnly: Boolean,
withImplicitReceiversWhenExplicitPresent: Boolean = false
): List<ReceiverType>? {
val languageVersionSettings = resolutionFacade.getLanguageVersionSettings()
val receiverExpression: KtExpression?
when (this) {
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
if (receiver != null) {
return when (val lhs = bindingContext[BindingContext.DOUBLE_COLON_LHS, receiver] ?: return emptyList()) {
is DoubleColonLHS.Type -> listOf(ReceiverType(lhs.type, 0))
is DoubleColonLHS.Expression -> {
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
receiverValueTypes(
receiverValue, lhs.dataFlowInfo, bindingContext,
moduleDescriptor, stableSmartCastsOnly,
resolutionFacade
).map { ReceiverType(it, 0) }
}
}
} else {
return emptyList()
}
}
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
is CallTypeAndReceiver.DOT -> receiverExpression = receiver
is CallTypeAndReceiver.SAFE -> receiverExpression = receiver
is CallTypeAndReceiver.INFIX -> receiverExpression = receiver
is CallTypeAndReceiver.OPERATOR -> receiverExpression = receiver
is CallTypeAndReceiver.DELEGATE -> receiverExpression = receiver
is CallTypeAndReceiver.SUPER_MEMBERS -> {
val qualifier = receiver.superTypeQualifier
return if (qualifier != null) {
listOfNotNull(bindingContext.getType(receiver)).map { ReceiverType(it, 0) }
} else {
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
val classDescriptor =
resolutionScope.ownerDescriptor.parentsWithSelf.firstIsInstanceOrNull<ClassDescriptor>() ?: return emptyList()
classDescriptor.typeConstructor.supertypesWithAny().map { ReceiverType(it, 0) }
}
}
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
is CallTypeAndReceiver.TYPE,
is CallTypeAndReceiver.ANNOTATION,
is CallTypeAndReceiver.UNKNOWN ->
return null
}
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
val expressionReceiver = receiverExpression?.let {
val receiverType =
bindingContext.getType(receiverExpression) ?: (bindingContext.get(
BindingContext.QUALIFIER,
receiverExpression
) as? ClassQualifier)?.descriptor?.classValueType ?: (bindingContext.get(
BindingContext.QUALIFIER,
receiverExpression
) as? TypeAliasQualifier)?.classDescriptor?.classValueType ?: return emptyList()
ExpressionReceiver.create(receiverExpression, receiverType, bindingContext)
}
val implicitReceiverValues = resolutionScope.getImplicitReceiversWithInstance(
excludeShadowedByDslMarkers = languageVersionSettings.supportsFeature(LanguageFeature.DslMarkersSupport)
).map { it.value }
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(contextElement)
val result = ArrayList<ReceiverType>()
var receiverIndex = 0
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
val types = receiverValueTypes(
receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly,
resolutionFacade
)
types.mapTo(result) { type -> ReceiverType(type, receiverIndex, receiverValue.takeIf { implicit }) }
receiverIndex++
}
if (withImplicitReceiversWhenExplicitPresent || expressionReceiver == null) {
implicitReceiverValues.forEach { addReceiverType(it, true) }
}
if (expressionReceiver != null) {
addReceiverType(expressionReceiver, false)
}
return result
}
@OptIn(FrontendInternals::class)
private fun receiverValueTypes(
receiverValue: ReceiverValue,
dataFlowInfo: DataFlowInfo,
bindingContext: BindingContext,
moduleDescriptor: ModuleDescriptor,
stableSmartCastsOnly: Boolean,
resolutionFacade: ResolutionFacade
): List<KotlinType> {
val languageVersionSettings = resolutionFacade.getLanguageVersionSettings()
val dataFlowValueFactory = resolutionFacade.getDataFlowValueFactory()
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
receiverValue,
bindingContext,
moduleDescriptor,
dataFlowInfo,
languageVersionSettings,
dataFlowValueFactory
)
} else {
listOf(receiverValue.type)
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("FuzzyTypeUtils")
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
import org.jetbrains.kotlin.types.typeUtil.*
import java.util.*
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
fun CallableDescriptor.fuzzyExtensionReceiverType() = extensionReceiverParameter?.type?.toFuzzyType(typeParameters)
fun FuzzyType.makeNotNullable() = type.makeNotNullable().toFuzzyType(freeParameters)
fun FuzzyType.makeNullable() = type.makeNullable().toFuzzyType(freeParameters)
fun FuzzyType.nullability() = type.nullability()
fun FuzzyType.isAlmostEverything(): Boolean {
if (freeParameters.isEmpty()) return false
val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
if (typeParameter !in freeParameters) return false
return typeParameter.upperBounds.singleOrNull()?.isAnyOrNullableAny() ?: false
}
/**
* Replaces free parameters inside the type with corresponding type parameters of the class (when possible)
*/
fun FuzzyType.presentationType(): KotlinType {
if (freeParameters.isEmpty()) return type
val map = HashMap<TypeConstructor, TypeProjection>()
for ((argument, typeParameter) in type.arguments.zip(type.constructor.parameters)) {
if (argument.projectionKind == Variance.INVARIANT) {
val equalToFreeParameter = freeParameters.firstOrNull {
StrictEqualityTypeChecker.strictEqualTypes(it.defaultType, argument.type.unwrap())
} ?: continue
map[equalToFreeParameter.typeConstructor] = createProjection(typeParameter.defaultType, Variance.INVARIANT, null)
}
}
val substitutor = TypeSubstitutor.create(map)
return substitutor.substitute(type, Variance.INVARIANT)!!
}
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>) = FuzzyType(this, freeParameters)
class FuzzyType(
val type: KotlinType,
freeParameters: Collection<TypeParameterDescriptor>
) {
val freeParameters: Set<TypeParameterDescriptor>
init {
if (freeParameters.isNotEmpty()) {
// we allow to pass type parameters from another function with the same original in freeParameters
val usedTypeParameters = HashSet<TypeParameterDescriptor>().apply { addUsedTypeParameters(type) }
if (usedTypeParameters.isNotEmpty()) {
val originalFreeParameters = freeParameters.map { it.toOriginal() }.toSet()
this.freeParameters = usedTypeParameters.filter { it.toOriginal() in originalFreeParameters }.toSet()
} else {
this.freeParameters = emptySet()
}
} else {
this.freeParameters = emptySet()
}
}
// Diagnostic for EA-109046
@Suppress("USELESS_ELVIS")
private fun TypeParameterDescriptor.toOriginal(): TypeParameterDescriptor {
val callableDescriptor = containingDeclaration as? CallableMemberDescriptor ?: return this
val original = callableDescriptor.original ?: error("original = null for $callableDescriptor")
val typeParameters = original.typeParameters ?: error("typeParameters = null for $original")
return typeParameters[index]
}
override fun equals(other: Any?) = other is FuzzyType && other.type == type && other.freeParameters == freeParameters
override fun hashCode() = type.hashCode()
private fun MutableSet<TypeParameterDescriptor>.addUsedTypeParameters(type: KotlinType) {
val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor
if (typeParameter != null && add(typeParameter)) {
typeParameter.upperBounds.forEach { addUsedTypeParameters(it) }
}
for (argument in type.arguments) {
if (!argument.isStarProjection) { // otherwise we can fall into infinite recursion
addUsedTypeParameters(argument.type)
}
}
}
fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
private enum class MatchKind {
IS_SUBTYPE,
IS_SUPERTYPE
}
private fun matchedSubstitutor(otherType: FuzzyType, matchKind: MatchKind): TypeSubstitutor? {
if (type.isError) return null
if (otherType.type.isError) return null
if (otherType.type.isUnit() && matchKind == MatchKind.IS_SUBTYPE) return TypeSubstitutor.EMPTY
fun KotlinType.checkInheritance(otherType: KotlinType): Boolean {
return when (matchKind) {
MatchKind.IS_SUBTYPE -> this.isSubtypeOf(otherType)
MatchKind.IS_SUPERTYPE -> otherType.isSubtypeOf(this)
}
}
if (freeParameters.isEmpty() && otherType.freeParameters.isEmpty()) {
return if (type.checkInheritance(otherType.type)) TypeSubstitutor.EMPTY else null
}
val builder = ConstraintSystemBuilderImpl()
val typeVariableSubstitutor = builder.registerTypeVariables(CallHandle.NONE, freeParameters + otherType.freeParameters)
val typeInSystem = typeVariableSubstitutor.substitute(type, Variance.INVARIANT)
val otherTypeInSystem = typeVariableSubstitutor.substitute(otherType.type, Variance.INVARIANT)
when (matchKind) {
MatchKind.IS_SUBTYPE ->
builder.addSubtypeConstraint(typeInSystem, otherTypeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
MatchKind.IS_SUPERTYPE ->
builder.addSubtypeConstraint(otherTypeInSystem, typeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
}
builder.fixVariables()
val constraintSystem = builder.build()
if (constraintSystem.status.hasContradiction()) return null
// currently ConstraintSystem return successful status in case there are problems with nullability
// that's why we have to check subtyping manually
val substitutor = constraintSystem.resultingSubstitutor
val substitutedType = substitutor.substitute(type, Variance.INVARIANT) ?: return null
if (substitutedType.isError) return TypeSubstitutor.EMPTY
val otherSubstitutedType = substitutor.substitute(otherType.type, Variance.INVARIANT) ?: return null
if (otherSubstitutedType.isError) return TypeSubstitutor.EMPTY
if (!substitutedType.checkInheritance(otherSubstitutedType)) return null
val substitutorToKeepCapturedTypes = object : DelegatedTypeSubstitution(substitutor.substitution) {
override fun approximateCapturedTypes() = false
}.buildSubstitutor()
val substitutionMap: Map<TypeConstructor, TypeProjection> = constraintSystem.typeVariables
.map { it.originalTypeParameter }
.associateBy(
keySelector = { it.typeConstructor },
valueTransform = {
val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType)
val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection)
substitutedProjection?.takeUnless { ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection
})
return TypeConstructorSubstitution.createByConstructorsMap(substitutionMap, approximateCapturedTypes = true).buildSubstitutor()
}
}
fun TypeSubstitution.hasConflictWith(other: TypeSubstitution, freeParameters: Collection<TypeParameterDescriptor>): Boolean {
return freeParameters.any { parameter ->
val type = parameter.defaultType
val substituted1 = this[type] ?: return@any false
val substituted2 = other[type] ?: return@any false
!StrictEqualityTypeChecker.strictEqualTypes(
substituted1.type.unwrap(),
substituted2.type.unwrap()
) || substituted1.projectionKind != substituted2.projectionKind
}
}
fun TypeSubstitutor.combineIfNoConflicts(other: TypeSubstitutor, freeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
if (this.substitution.hasConflictWith(other.substitution, freeParameters)) return null
return TypeSubstitutor.createChainedSubstitutor(this.substitution, other.substitution)
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:JvmName("ImportsUtils")
package org.jetbrains.kotlin.idea.imports
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
val DeclarationDescriptor.importableFqName: FqName?
get() {
if (!canBeReferencedViaImport()) return null
return getImportableDescriptor().fqNameSafe
}
fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
if (this is PackageViewDescriptor ||
DescriptorUtils.isTopLevelDeclaration(this) ||
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)
) {
return !name.isSpecial
}
//Both TypeAliasDescriptor and ClassDescriptor
val parentClassifier = containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: return false
if (!parentClassifier.canBeReferencedViaImport()) return false
return when (this) {
is ConstructorDescriptor -> !parentClassifier.isInner // inner class constructors can't be referenced via import
is ClassDescriptor, is TypeAliasDescriptor -> true
else -> parentClassifier is ClassDescriptor && parentClassifier.kind == ClassKind.OBJECT
}
}
fun DeclarationDescriptor.canBeAddedToImport(): Boolean = this !is PackageViewDescriptor && canBeReferencedViaImport()
fun KotlinType.canBeReferencedViaImport(): Boolean {
val descriptor = constructor.declarationDescriptor
return descriptor != null && descriptor.canBeReferencedViaImport()
}
// for cases when class qualifier refers companion object treats it like reference to class itself
fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, this]?.let { listOf(it) }
?: getReferenceTargets(bindingContext)
return targets.map { it.getImportableDescriptor() }.toSet()
}
fun KtImportDirective.canResolve(facade: ResolutionFacade): Boolean {
return (importedReference?.getQualifiedElementSelector() as? KtSimpleNameExpression)?.let { nameExpression ->
nameExpression.getImportableTargets(facade.analyze(nameExpression, BodyResolveMode.PARTIAL)).isNotEmpty()
} ?: false
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
fun FunctionDescriptor.shouldNotConvertToProperty(notProperties: Set<FqNameUnsafe>): Boolean {
if (fqNameUnsafe in notProperties) return true
return this.overriddenTreeUniqueAsSequence(false).any { fqNameUnsafe in notProperties }
}
fun SyntheticJavaPropertyDescriptor.suppressedByNotPropertyList(set: Set<FqNameUnsafe>) =
getMethod.shouldNotConvertToProperty(set) || setMethod?.shouldNotConvertToProperty(set) ?: false

View File

@@ -0,0 +1,256 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.resolve.getDataFlowValueFactory
import org.jetbrains.kotlin.idea.resolve.getLanguageVersionSettings
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.addImportingScope
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
import java.util.*
class ShadowedDeclarationsFilter(
private val bindingContext: BindingContext,
private val resolutionFacade: ResolutionFacade,
private val context: PsiElement,
private val explicitReceiverValue: ReceiverValue?
) {
companion object {
fun create(
bindingContext: BindingContext,
resolutionFacade: ResolutionFacade,
context: PsiElement,
callTypeAndReceiver: CallTypeAndReceiver<*, *>
): ShadowedDeclarationsFilter? {
val receiverExpression = when (callTypeAndReceiver) {
is CallTypeAndReceiver.DEFAULT -> null
is CallTypeAndReceiver.DOT -> callTypeAndReceiver.receiver
is CallTypeAndReceiver.SAFE -> callTypeAndReceiver.receiver
is CallTypeAndReceiver.SUPER_MEMBERS -> callTypeAndReceiver.receiver
is CallTypeAndReceiver.INFIX -> callTypeAndReceiver.receiver
is CallTypeAndReceiver.TYPE, is CallTypeAndReceiver.ANNOTATION -> null // need filtering of classes with the same FQ-name
else -> return null // TODO: support shadowed declarations filtering for callable references
}
val explicitReceiverValue = receiverExpression?.let {
val type = bindingContext.getType(it) ?: return null
ExpressionReceiver.create(it, type, bindingContext)
}
return ShadowedDeclarationsFilter(bindingContext, resolutionFacade, context, explicitReceiverValue)
}
}
private val psiFactory = KtPsiFactory(resolutionFacade.project)
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> =
declarations.groupBy { signature(it) }.values.flatMap { group -> filterEqualSignatureGroup(group) }
fun <TDescriptor : DeclarationDescriptor> createNonImportedDeclarationsFilter(
importedDeclarations: Collection<DeclarationDescriptor>
): (Collection<TDescriptor>) -> Collection<TDescriptor> {
val importedDeclarationsSet = importedDeclarations.toSet()
val importedDeclarationsBySignature = importedDeclarationsSet.groupBy { signature(it) }
return filter@{ declarations ->
// optimization
if (declarations.size == 1 && importedDeclarationsBySignature[signature(declarations.single())] == null) return@filter declarations
val nonImportedDeclarations = declarations.filter { it !in importedDeclarationsSet }
val notShadowed = HashSet<DeclarationDescriptor>()
// same signature non-imported declarations from different packages do not shadow each other
for ((pair, group) in nonImportedDeclarations.groupBy { signature(it) to packageName(it) }) {
val imported = importedDeclarationsBySignature[pair.first]
val all = if (imported != null) group + imported else group
notShadowed.addAll(filterEqualSignatureGroup(all, descriptorsToImport = group))
}
declarations.filter { it in notShadowed }
}
}
private fun signature(descriptor: DeclarationDescriptor): Any = when (descriptor) {
is SimpleFunctionDescriptor -> FunctionSignature(descriptor)
is VariableDescriptor -> descriptor.name
is ClassDescriptor -> descriptor.importableFqName ?: descriptor
else -> descriptor
}
private fun packageName(descriptor: DeclarationDescriptor) = descriptor.importableFqName?.parent()
private fun <TDescriptor : DeclarationDescriptor> filterEqualSignatureGroup(
descriptors: Collection<TDescriptor>,
descriptorsToImport: Collection<TDescriptor> = emptyList()
): Collection<TDescriptor> {
if (descriptors.size == 1) return descriptors
val first = descriptors.firstOrNull {
it is ClassDescriptor || it is ConstructorDescriptor || it is CallableDescriptor && !it.name.isSpecial
} ?: return descriptors
if (first is ClassDescriptor) { // for classes with the same FQ-name we simply take the first one
return listOf(first)
}
val isFunction = first is FunctionDescriptor
val name = when (first) {
is ConstructorDescriptor -> first.constructedClass.name
else -> first.name
}
val parameters = (first as CallableDescriptor).valueParameters
val dummyArgumentExpressions = dummyExpressionFactory.createDummyExpressions(parameters.size)
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for filtering shadowed declarations")
for ((expression, parameter) in dummyArgumentExpressions.zip(parameters)) {
bindingTrace.recordType(expression, parameter.varargElementType ?: parameter.type)
bindingTrace.record(BindingContext.PROCESSED, expression, true)
}
val firstVarargIndex = parameters.withIndex().firstOrNull { it.value.varargElementType != null }?.index
val useNamedFromIndex =
if (firstVarargIndex != null && firstVarargIndex != parameters.lastIndex) firstVarargIndex else parameters.size
class DummyArgument(val index: Int) : ValueArgument {
private val expression = dummyArgumentExpressions[index]
private val argumentName: ValueArgumentName? = if (isNamed()) {
object : ValueArgumentName {
override val asName = parameters[index].name
override val referenceExpression = null
}
} else {
null
}
override fun getArgumentExpression() = expression
override fun isNamed() = index >= useNamedFromIndex
override fun getArgumentName() = argumentName
override fun asElement() = expression
override fun getSpreadElement() = null
override fun isExternal() = false
}
val arguments = ArrayList<DummyArgument>()
for (i in parameters.indices) {
arguments.add(DummyArgument(i))
}
val newCall = object : Call {
//TODO: compiler crash (KT-8011)
//val arguments = parameters.indices.map { DummyArgument(it) }
val callee = psiFactory.createExpressionByPattern("$0", name, reformat = false)
override fun getCalleeExpression() = callee
override fun getValueArgumentList() = null
override fun getValueArguments() = arguments
override fun getFunctionLiteralArguments() = emptyList<LambdaArgument>()
override fun getTypeArguments() = emptyList<KtTypeProjection>()
override fun getTypeArgumentList() = null
override fun getDispatchReceiver() = null
override fun getCallOperationNode() = null
override fun getExplicitReceiver() = explicitReceiverValue
override fun getCallElement() = callee
override fun getCallType() = Call.CallType.DEFAULT
}
var scope = context.getResolutionScope(bindingContext, resolutionFacade)
if (descriptorsToImport.isNotEmpty()) {
scope = scope.addImportingScope(ExplicitImportsScope(descriptorsToImport))
}
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
val context = BasicCallResolutionContext.create(
bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
false, resolutionFacade.getLanguageVersionSettings(),
resolutionFacade.getDataFlowValueFactory()
)
@OptIn(FrontendInternals::class)
val callResolver = resolutionFacade.frontendService<CallResolver>()
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.original }
val filtered = descriptors.filter { candidateDescriptor ->
candidateDescriptor.original in resultingOriginals /* optimization */ && resultingDescriptors.any {
descriptorsEqualWithSubstitution(
it,
candidateDescriptor
)
}
}
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
}
private class DummyExpressionFactory(val factory: KtPsiFactory) {
private val expressions = ArrayList<KtExpression>()
fun createDummyExpressions(count: Int): List<KtExpression> {
while (expressions.size < count) {
expressions.add(factory.createExpression("dummy"))
}
return expressions.take(count)
}
}
private class FunctionSignature(val function: FunctionDescriptor) {
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is FunctionSignature) return false
if (function.name != other.function.name) return false
val parameters1 = function.valueParameters
val parameters2 = other.function.valueParameters
if (parameters1.size != parameters2.size) return false
for (i in parameters1.indices) {
val p1 = parameters1[i]
val p2 = parameters2[i]
if (p1.varargElementType != p2.varargElementType) return false // both should be vararg or or both not
if (p1.type != p2.type) return false
}
val typeParameters1 = function.typeParameters
val typeParameters2 = other.function.typeParameters
if (typeParameters1.size != typeParameters2.size) return false
for (i in typeParameters1.indices) {
val t1 = typeParameters1[i]
val t2 = typeParameters2[i]
if (t1.upperBounds != t2.upperBounds) return false
}
return true
}
override fun hashCode() = function.name.hashCode() * 17 + function.valueParameters.size
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("TypeUtils")
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.*
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper
import org.jetbrains.kotlin.builtins.replaceReturnType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
import org.jetbrains.kotlin.load.java.lazy.child
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeAttributes
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeParameterImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.SmartSet
fun KotlinType.approximateFlexibleTypes(
preferNotNull: Boolean = false,
preferStarForRaw: Boolean = false
): KotlinType {
if (isDynamic()) return this
return unwrapEnhancement().approximateNonDynamicFlexibleTypes(preferNotNull, preferStarForRaw)
}
private fun KotlinType.approximateNonDynamicFlexibleTypes(
preferNotNull: Boolean = false,
preferStarForRaw: Boolean = false
): SimpleType {
if (this is ErrorType) return this
if (isFlexible()) {
val flexible = asFlexibleType()
val lowerClass = flexible.lowerBound.constructor.declarationDescriptor as? ClassDescriptor?
val isCollection = lowerClass != null && JavaToKotlinClassMapper.isMutable(lowerClass)
// (Mutable)Collection<T>! -> MutableCollection<T>?
// Foo<(Mutable)Collection<T>!>! -> Foo<Collection<T>>?
// Foo! -> Foo?
// Foo<Bar!>! -> Foo<Bar>?
var approximation =
if (isCollection)
flexible.lowerBound.makeNullableAsSpecified(!preferNotNull)
else
if (this is RawType && preferStarForRaw) flexible.upperBound.makeNullableAsSpecified(!preferNotNull)
else
if (preferNotNull) flexible.lowerBound else flexible.upperBound
approximation = approximation.approximateNonDynamicFlexibleTypes()
approximation = if (nullability() == TypeNullability.NOT_NULL) approximation.makeNullableAsSpecified(false) else approximation
if (approximation.isMarkedNullable && !flexible.lowerBound
.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)
) {
approximation = approximation.makeNullableAsSpecified(false)
}
return approximation
}
(unwrap() as? AbbreviatedType)?.let {
return AbbreviatedType(it.expandedType, it.abbreviation.approximateNonDynamicFlexibleTypes(preferNotNull))
}
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
annotations,
constructor,
arguments.map { it.substitute { type -> type.approximateFlexibleTypes(preferNotNull = true) } },
isMarkedNullable,
ErrorUtils.createErrorScope("This type is not supposed to be used in member resolution", true)
)
}
fun KotlinType.isResolvableInScope(scope: LexicalScope?, checkTypeParameters: Boolean, allowIntersections: Boolean = false): Boolean {
if (constructor is IntersectionTypeConstructor) {
if (!allowIntersections) return false
return constructor.supertypes.all { it.isResolvableInScope(scope, checkTypeParameters, allowIntersections) }
}
if (canBeReferencedViaImport()) return true
val descriptor = constructor.declarationDescriptor
if (descriptor == null || descriptor.name.isSpecial) return false
if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true
return scope != null && scope.findClassifier(descriptor.name, NoLookupLocation.FROM_IDE) == descriptor
}
fun KotlinType.approximateWithResolvableType(scope: LexicalScope?, checkTypeParameters: Boolean): KotlinType {
if (isError || isResolvableInScope(scope, checkTypeParameters)) return this
return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
?: builtIns.anyType
}
fun KotlinType.anonymousObjectSuperTypeOrNull(): KotlinType? {
val classDescriptor = constructor.declarationDescriptor
if (classDescriptor != null && DescriptorUtils.isAnonymousObject(classDescriptor)) {
return immediateSupertypes().firstOrNull() ?: classDescriptor.builtIns.anyType
}
return null
}
fun KotlinType.getResolvableApproximations(
scope: LexicalScope?,
checkTypeParameters: Boolean,
allowIntersections: Boolean = false
): Sequence<KotlinType> {
return (listOf(this) + TypeUtils.getAllSupertypes(this))
.asSequence()
.mapNotNull {
it.asTypeProjection()
.fixTypeProjection(scope, checkTypeParameters, allowIntersections, isOutVariance = true)
?.type
}
}
private fun TypeProjection.fixTypeProjection(
scope: LexicalScope?,
checkTypeParameters: Boolean,
allowIntersections: Boolean,
isOutVariance: Boolean
): TypeProjection? {
if (!type.isResolvableInScope(scope, checkTypeParameters, allowIntersections)) return null
if (type.arguments.isEmpty()) return this
val resolvableArgs = type.arguments.filterTo(SmartSet.create()) { typeProjection ->
typeProjection.type.isResolvableInScope(scope, checkTypeParameters, allowIntersections)
}
if (resolvableArgs.containsAll(type.arguments)) {
fun fixArguments(type: KotlinType): KotlinType? = type.replace(
(type.arguments zip type.constructor.parameters).map { (arg, param) ->
if (arg.isStarProjection) arg
else arg.fixTypeProjection(
scope,
checkTypeParameters,
allowIntersections,
isOutVariance = isOutVariance && param.variance == Variance.OUT_VARIANCE
) ?: when {
!isOutVariance -> return null
param.variance == Variance.OUT_VARIANCE -> arg.type.approximateWithResolvableType(
scope,
checkTypeParameters
).asTypeProjection()
else -> type.replaceArgumentsWithStarProjections().arguments.first()
}
})
return if (type.isBuiltinFunctionalType) {
val returnType = type.getReturnTypeFromFunctionType()
type.replaceReturnType(fixArguments(returnType) ?: return null).asTypeProjection()
} else fixArguments(type)?.asTypeProjection()
}
if (!isOutVariance) return null
val newArguments = (type.arguments zip type.constructor.parameters).map { (arg, param) ->
when {
arg in resolvableArgs -> arg
arg.projectionKind == Variance.OUT_VARIANCE ||
param.variance == Variance.OUT_VARIANCE -> TypeProjectionImpl(
arg.projectionKind,
arg.type.approximateWithResolvableType(scope, checkTypeParameters)
)
else -> return if (isOutVariance) type.replaceArgumentsWithStarProjections().asTypeProjection() else null
}
}
return type.replace(newArguments).asTypeProjection()
}
fun KotlinType.isAbstract(): Boolean {
val modality = (constructor.declarationDescriptor as? ClassDescriptor)?.modality
return modality == Modality.ABSTRACT || modality == Modality.SEALED
}
/**
* NOTE: this is a very shaky implementation of [PsiType] to [KotlinType] conversion,
* produced types are fakes and are usable only for code generation. Please be careful using this method.
*/
@OptIn(FrontendInternals::class)
fun PsiType.resolveToKotlinType(resolutionFacade: ResolutionFacade): KotlinType {
if (this == PsiType.NULL) {
return resolutionFacade.moduleDescriptor.builtIns.nullableAnyType
}
val typeParameters = collectTypeParameters()
val components = resolutionFacade.getFrontendService(JavaResolverComponents::class.java)
val rootContext = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
val dummyPackageDescriptor = MutablePackageFragmentDescriptor(resolutionFacade.moduleDescriptor, FqName("dummy"))
val dummyClassDescriptor = ClassDescriptorImpl(
dummyPackageDescriptor,
Name.identifier("Dummy"),
Modality.FINAL,
ClassKind.CLASS,
emptyList(),
SourceElement.NO_SOURCE,
false,
LockBasedStorageManager.NO_LOCKS
)
val typeParameterResolver = object : TypeParameterResolver {
override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? {
val psiTypeParameter = (javaTypeParameter as JavaTypeParameterImpl).psi
val index = typeParameters.indexOf(psiTypeParameter)
if (index < 0) return null
return LazyJavaTypeParameterDescriptor(rootContext.child(this), javaTypeParameter, index, dummyClassDescriptor)
}
}
val typeResolver = JavaTypeResolver(rootContext, typeParameterResolver)
val attributes = JavaTypeAttributes(TypeUsage.COMMON)
return typeResolver.transformJavaType(JavaTypeImpl.create(this), attributes).approximateFlexibleTypes(preferNotNull = true)
}
private fun PsiType.collectTypeParameters(): List<PsiTypeParameter> {
val results = ArrayList<PsiTypeParameter>()
accept(
object : PsiTypeVisitor<Unit>() {
override fun visitArrayType(arrayType: PsiArrayType) {
arrayType.componentType.accept(this)
}
override fun visitClassType(classType: PsiClassType) {
(classType.resolve() as? PsiTypeParameter)?.let { results += it }
classType.parameters.forEach { it.accept(this) }
}
override fun visitWildcardType(wildcardType: PsiWildcardType) {
wildcardType.bound?.accept(this)
}
}
)
return results
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.FlexibleType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
receiverToCast: ReceiverValue,
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): List<KotlinType> {
val variants = getSmartCastVariants(
receiverToCast,
bindingContext,
containingDeclarationOrModule,
dataFlowInfo,
languageVersionSettings,
dataFlowValueFactory
)
return variants.filter { type ->
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } }
}
}
private fun chooseMoreSpecific(type1: KotlinType, type2: KotlinType): KotlinType? {
val type1IsSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(type1, type2)
val type2IsSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(type2, type1)
when {
type1IsSubtype && !type2IsSubtype -> return type1
type2IsSubtype && !type1IsSubtype -> return type2
!type1IsSubtype && !type2IsSubtype -> return null
else -> { // type1IsSubtype && type2IsSubtype
val flexible1 = type1.unwrap() as? FlexibleType
val flexible2 = type2.unwrap() as? FlexibleType
return when {
flexible1 != null && flexible2 == null -> type2
flexible2 != null && flexible1 == null -> type1
else -> null //TODO?
}
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("ExtensionUtils")
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.nullability
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
receiverTypes: Collection<KotlinType>,
callType: CallType<*>
): Collection<TCallable> {
if (!callType.descriptorKindFilter.accepts(this)) return listOf()
var types = receiverTypes.asSequence()
if (callType == CallType.SAFE) {
types = types.map { it.makeNotNullable() }
}
val extensionReceiverType = fuzzyExtensionReceiverType()!!
val substitutors = types.mapNotNull {
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
// check if we may fail due to receiver expression being nullable
if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) {
substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
}
substitutor
}
return if (typeParameters.isEmpty()) { // optimization for non-generic callables
if (substitutors.any()) listOf(this) else listOf()
} else {
substitutors
.mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) }
.toList()
}
}
fun ReceiverValue?.getThisReceiverOwner(bindingContext: BindingContext): DeclarationDescriptor? {
return when (this) {
is ExpressionReceiver -> {
val thisRef = (KtPsiUtil.deparenthesize(this.expression) as? KtThisExpression)?.instanceReference ?: return null
bindingContext[BindingContext.REFERENCE_TARGET, thisRef]
}
is ImplicitReceiver -> this.declarationDescriptor
else -> null
}
}
fun ReceiverValue?.getReceiverTargetDescriptor(bindingContext: BindingContext): DeclarationDescriptor? = when (this) {
is ExpressionReceiver -> when (val expression = KtPsiUtil.deparenthesize(this.expression)) {
is KtThisExpression -> expression.instanceReference
is KtReferenceExpression -> expression
else -> null
}?.let { referenceExpression ->
bindingContext[BindingContext.REFERENCE_TARGET, referenceExpression]
}
is ImplicitReceiver -> this.declarationDescriptor
else -> null
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import java.util.*
import kotlin.collections.LinkedHashSet
fun LexicalScope.getImplicitReceiversWithInstance(excludeShadowedByDslMarkers: Boolean = false): Collection<ReceiverParameterDescriptor> =
getImplicitReceiversWithInstanceToExpression(excludeShadowedByDslMarkers).keys
interface ReceiverExpressionFactory {
val isImmediate: Boolean
val expressionText: String
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
}
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? =
getImplicitReceiversWithInstanceToExpression().entries.firstOrNull { (receiverDescriptor, _) ->
receiverDescriptor.type.isSubtypeOf(receiverType)
}?.value
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(
excludeShadowedByDslMarkers: Boolean = false
): Map<ReceiverParameterDescriptor, ReceiverExpressionFactory?> {
val allReceivers = getImplicitReceiversHierarchy()
// we use a set to workaround a bug with receiver for companion object present twice in the result of getImplicitReceiversHierarchy()
val receivers = LinkedHashSet(
if (excludeShadowedByDslMarkers) {
allReceivers - allReceivers.shadowedByDslMarkers()
} else {
allReceivers
}
)
val outerDeclarationsWithInstance = LinkedHashSet<DeclarationDescriptor>()
var current: DeclarationDescriptor? = ownerDescriptor
while (current != null) {
if (current is PropertyAccessorDescriptor) {
current = current.correspondingProperty
}
outerDeclarationsWithInstance.add(current)
val classDescriptor = current as? ClassDescriptor
if (classDescriptor != null && !classDescriptor.isInner && !DescriptorUtils.isLocal(classDescriptor)) break
current = current.containingDeclaration
}
val result = LinkedHashMap<ReceiverParameterDescriptor, ReceiverExpressionFactory?>()
for ((index, receiver) in receivers.withIndex()) {
val owner = receiver.containingDeclaration
if (owner is ScriptDescriptor) {
result[receiver] = null
outerDeclarationsWithInstance.addAll(owner.implicitReceivers)
continue
}
val (expressionText, isImmediateThis) = if (owner in outerDeclarationsWithInstance) {
val thisWithLabel = thisQualifierName(receiver)?.let { "this@${it.render()}" }
if (index == 0)
(thisWithLabel ?: "this") to true
else
thisWithLabel to false
} else if (owner is ClassDescriptor && owner.kind.isSingleton) {
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(owner) to false
} else {
continue
}
val factory = if (expressionText != null)
object : ReceiverExpressionFactory {
override val isImmediate = isImmediateThis
override val expressionText: String get() = expressionText
override fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean): KtExpression {
return psiFactory.createExpression(if (shortThis && isImmediateThis) "this" else expressionText)
}
}
else
null
result[receiver] = factory
}
return result
}
private fun thisQualifierName(receiver: ReceiverParameterDescriptor): Name? {
val descriptor = receiver.containingDeclaration
val name = descriptor.name
if (!name.isSpecial) return name
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtFunctionLiteral
return functionLiteral?.findLabelAndCall()?.first
}
private fun List<ReceiverParameterDescriptor>.shadowedByDslMarkers(): Set<ReceiverParameterDescriptor> {
val typesByDslScopes = mutableMapOf<FqName, MutableList<ReceiverParameterDescriptor>>()
for (receiver in this) {
val dslMarkers = DslMarkerUtils.extractDslMarkerFqNames(receiver.value).all()
for (marker in dslMarkers) {
typesByDslScopes.getOrPut(marker) { mutableListOf() } += receiver
}
}
// for each DSL marker, all receivers except the closest one are shadowed by it; that is why we drop it
return typesByDslScopes.values.flatMapTo(mutableSetOf()) { it.drop(1) }
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("ScopeUtils")
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescriptor> {
return getVariablesFromImplicitReceivers(name) + collectVariables(name, NoLookupLocation.FROM_IDE)
}
fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> {
return getImplicitReceiversWithInstance().flatMap {
it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
} + collectFunctions(name, NoLookupLocation.FROM_IDE)
}
fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> =
getImplicitReceiversWithInstance().flatMap {
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
}
fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? {
getImplicitReceiversWithInstance().forEach {
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE).singleOrNull()?.let { return it }
}
return null
}
fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope? {
for (parent in parentsWithSelf) {
if (parent is KtElement) {
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent]
if (scope != null) return scope
}
if (parent is KtClassBody) {
val classDescriptor = bindingContext[BindingContext.CLASS, parent.getParent()] as? ClassDescriptorWithResolutionScopes
if (classDescriptor != null) {
return classDescriptor.scopeForMemberDeclarationResolution
}
}
if (parent is KtFile) {
break
}
}
return null
}
fun PsiElement.getResolutionScope(
bindingContext: BindingContext,
resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/
): LexicalScope = getResolutionScope(bindingContext) ?: when (containingFile) {
is KtFile -> resolutionFacade.getFileResolutionScope(containingFile as KtFile)
else -> error("Not in KtFile")
}
fun KtElement.getResolutionScope(): LexicalScope {
val resolutionFacade = getResolutionFacade()
val context = resolutionFacade.analyze(this, BodyResolveMode.FULL)
return getResolutionScope(context, resolutionFacade)
}
@OptIn(FrontendInternals::class)
fun ResolutionFacade.getFileResolutionScope(file: KtFile): LexicalScope {
return frontendService<FileScopeProvider>().getFileResolutionScope(file)
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.scopes
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class ExplicitImportsScope(private val descriptors: Collection<DeclarationDescriptor>) : BaseImportingScope(null) {
override fun getContributedClassifier(name: Name, location: LookupLocation) =
descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
override fun getContributedPackage(name: Name) = descriptors.filter { it.name == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
override fun getContributedVariables(name: Name, location: LookupLocation) =
descriptors.filter { it.name == name }.filterIsInstance<VariableDescriptor>()
override fun getContributedFunctions(name: Name, location: LookupLocation) =
descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>()
override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
changeNamesForAliased: Boolean
) = descriptors
override fun computeImportedNames() = descriptors.mapTo(hashSetOf()) { it.name }
override fun printStructure(p: Printer) {
p.println(this::class.java.name)
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
fun descriptorsEqualWithSubstitution(
descriptor1: DeclarationDescriptor?,
descriptor2: DeclarationDescriptor?,
checkOriginals: Boolean = true
): Boolean {
if (descriptor1 == descriptor2) return true
if (descriptor1 == null || descriptor2 == null) return false
if (checkOriginals && descriptor1.original != descriptor2.original) return false
if (descriptor1 !is CallableDescriptor) return true
descriptor2 as CallableDescriptor
val typeChecker = KotlinTypeCheckerImpl.withAxioms(object : KotlinTypeChecker.TypeConstructorEquality {
override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
if (typeParam1 != null
&& typeParam2 != null
&& typeParam1.containingDeclaration == descriptor1
&& typeParam2.containingDeclaration == descriptor2
) {
return typeParam1.index == typeParam2.index
}
return a == b
}
})
if (!typeChecker.equalTypesOrNulls(descriptor1.returnType, descriptor2.returnType)) return false
val parameters1 = descriptor1.valueParameters
val parameters2 = descriptor2.valueParameters
if (parameters1.size != parameters2.size) return false
for ((param1, param2) in parameters1.zip(parameters2)) {
if (!typeChecker.equalTypes(param1.type, param2.type)) return false
}
return true
}
fun ClassDescriptor.findCallableMemberBySignature(
signature: CallableMemberDescriptor,
allowOverridabilityConflicts: Boolean = false
): CallableMemberDescriptor? {
val descriptorKind = if (signature is FunctionDescriptor) DescriptorKindFilter.FUNCTIONS else DescriptorKindFilter.VARIABLES
return defaultType.memberScope
.getContributedDescriptors(descriptorKind)
.filterIsInstance<CallableMemberDescriptor>()
.firstOrNull {
if (it.containingDeclaration != this) return@firstOrNull false
val overridability = OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result
overridability == OVERRIDABLE || (allowOverridabilityConflicts && overridability == CONFLICT)
}
}
fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> {
val supertypes = supertypes
val noSuperClass = supertypes.map { it.constructor.declarationDescriptor as? ClassDescriptor }.all {
it == null || it.kind == ClassKind.INTERFACE
}
return if (noSuperClass) supertypes + builtIns.anyType else supertypes
}
val ClassifierDescriptorWithTypeParameters.constructors: Collection<ConstructorDescriptor>
get() = when (this) {
is TypeAliasDescriptor -> this.constructors
is ClassDescriptor -> this.constructors
else -> emptyList()
}
val ClassifierDescriptorWithTypeParameters.kind: ClassKind?
get() = when (this) {
is TypeAliasDescriptor -> classDescriptor?.kind
is ClassDescriptor -> kind
else -> null
}
val DeclarationDescriptor.isJavaDescriptor
get() = this is JavaClassDescriptor || this is JavaCallableMemberDescriptor