ExpectActualUtils: merge generateFunction with generateProperty to generateCallable & remove old checker

This commit is contained in:
Dmitry Gridin
2019-08-22 14:38:53 +07:00
parent 90b82c96eb
commit 42ef9d634a
4 changed files with 48 additions and 203 deletions
@@ -21,8 +21,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
@@ -60,12 +59,9 @@ class AddActualFix(
val checker = TypeAccessibilityChecker.create(project, module) val checker = TypeAccessibilityChecker.create(project, module)
for (missedDeclaration in missedDeclarationPointers.mapNotNull { it.element }) { for (missedDeclaration in missedDeclarationPointers.mapNotNull { it.element }) {
val actualDeclaration = when (missedDeclaration) { val actualDeclaration = when (missedDeclaration) {
is KtClassOrObject -> factory.generateClassOrObject(project, false, missedDeclaration, checker, listOf(element)) is KtClassOrObject -> factory.generateClassOrObject(project, false, missedDeclaration, checker)
is KtFunction -> missedDeclaration.toDescriptor()?.safeAs<FunctionDescriptor>()?.let { is KtFunction, is KtProperty -> missedDeclaration.toDescriptor()?.safeAs<CallableMemberDescriptor>()?.let {
generateFunction(project, false, missedDeclaration, it, element, checker = checker) generateCallable(project, false, missedDeclaration, it, element, checker = checker)
}
is KtProperty -> missedDeclaration.toDescriptor()?.safeAs<PropertyDescriptor>()?.let {
generateProperty(project, false, missedDeclaration, it, element, checker = checker)
} }
else -> null else -> null
} ?: continue } ?: continue
@@ -21,8 +21,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
@@ -74,8 +73,11 @@ sealed class CreateActualFix<D : KtNamedDeclaration>(
val actualPlatform = actualModuleDescriptor.platform ?: return null val actualPlatform = actualModuleDescriptor.platform ?: return null
return when (declaration) { return when (declaration) {
is KtClassOrObject -> CreateActualClassFix(declaration, actualModule, actualPlatform) is KtClassOrObject -> CreateActualClassFix(declaration, actualModule, actualPlatform)
is KtFunction -> CreateActualFunctionFix(declaration, actualModule, actualPlatform) is KtFunction, is KtProperty -> CreateActualCallableMemberFix(
is KtProperty -> CreateActualPropertyFix(declaration, actualModule, actualPlatform) declaration as KtCallableDeclaration,
actualModule,
actualPlatform
)
else -> null else -> null
} }
} }
@@ -90,21 +92,12 @@ class CreateActualClassFix(
generateClassOrObject(project, false, element, checker = checker) generateClassOrObject(project, false, element, checker = checker)
}) })
class CreateActualPropertyFix( class CreateActualCallableMemberFix(
property: KtProperty, declaration: KtCallableDeclaration,
actualModule: Module, actualModule: Module,
actualPlatform: TargetPlatform actualPlatform: TargetPlatform
) : CreateActualFix<KtProperty>(property, actualModule, actualPlatform, { project, checker, element -> ) : CreateActualFix<KtCallableDeclaration>(declaration, actualModule, actualPlatform, { project, checker, element ->
val descriptor = element.toDescriptor() as? PropertyDescriptor val descriptor = element.toDescriptor() as? CallableMemberDescriptor
descriptor?.let { generateProperty(project, false, element, descriptor, checker = checker) } descriptor?.let { generateCallable(project, false, element, descriptor, checker = checker) }
})
class CreateActualFunctionFix(
function: KtFunction,
actualModule: Module,
actualPlatform: TargetPlatform
) : CreateActualFix<KtFunction>(function, actualModule, actualPlatform, { project, checker, element ->
val descriptor = element.toDescriptor() as? FunctionDescriptor
descriptor?.let { generateFunction(project, false, element, descriptor, checker = checker) }
}) })
@@ -13,10 +13,9 @@ import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.showOkNoDialog import com.intellij.openapi.ui.showOkNoDialog
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
@@ -90,10 +89,9 @@ sealed class CreateExpectedFix<D : KtNamedDeclaration>(
?: return emptyList() ?: return emptyList()
return when (actualDeclaration) { return when (actualDeclaration) {
is KtClassOrObject -> expectedModules.map { CreateExpectedClassFix(actualDeclaration, expectedContainingClass, it) } is KtClassOrObject -> expectedModules.map { CreateExpectedClassFix(actualDeclaration, expectedContainingClass, it) }
is KtFunction -> expectedModules.map { CreateExpectedFunctionFix(actualDeclaration, expectedContainingClass, it) } is KtProperty, is KtParameter, is KtFunction -> expectedModules.map {
is KtProperty, is KtParameter -> expectedModules.map { CreateExpectedCallableMemberFix(
CreateExpectedPropertyFix( actualDeclaration as KtCallableDeclaration,
actualDeclaration,
expectedContainingClass, expectedContainingClass,
it it
) )
@@ -163,7 +161,7 @@ class CreateExpectedClassFix(
repairActualModifiers(originalElements + klass, resultDeclarations.toSet()) repairActualModifiers(originalElements + klass, resultDeclarations.toSet())
} }
generateClassOrObject(project, true, element, checker, listOfNotNull(outerExpectedClass)) generateClassOrObject(project, true, element, checker)
}) })
private tailrec fun TypeAccessibilityChecker.findAndApplyExistingClasses(elements: Collection<KtNamedDeclaration>): HashSet<String> { private tailrec fun TypeAccessibilityChecker.findAndApplyExistingClasses(elements: Collection<KtNamedDeclaration>): HashSet<String> {
@@ -294,42 +292,19 @@ private fun KtNamedDeclaration.selected(): Sequence<KtNamedDeclaration> {
return sequenceOf(this) + additionalSequence + containingClassOrObject?.selected().orEmpty() return sequenceOf(this) + additionalSequence + containingClassOrObject?.selected().orEmpty()
} }
class CreateExpectedPropertyFix( class CreateExpectedCallableMemberFix(
property: KtNamedDeclaration, declaration: KtCallableDeclaration,
targetExpectedClass: KtClassOrObject?, targetExpectedClass: KtClassOrObject?,
commonModule: Module commonModule: Module
) : CreateExpectedFix<KtNamedDeclaration>(property, targetExpectedClass, commonModule, block@{ project, checker, element -> ) : CreateExpectedFix<KtNamedDeclaration>(declaration, targetExpectedClass, commonModule, block@{ project, checker, element ->
if (!checker.checkAccessibility(element)) { if (!checker.checkAccessibility(element)) {
showUnknownTypesError(element) showUnknownTypesError(element)
return@block null return@block null
} }
val descriptor = element.toDescriptor() as? PropertyDescriptor val descriptor = element.toDescriptor() as? CallableMemberDescriptor
checker.existingFqNames = targetExpectedClass?.getSuperNames()?.toSet().orEmpty() checker.existingFqNames = targetExpectedClass?.getSuperNames()?.toSet().orEmpty()
descriptor?.let { descriptor?.let {
generateProperty( generateCallable(
project,
true,
element,
descriptor,
targetExpectedClass,
checker = checker
)
}
})
class CreateExpectedFunctionFix(
function: KtFunction,
targetExpectedClass: KtClassOrObject?,
commonModule: Module
) : CreateExpectedFix<KtFunction>(function, targetExpectedClass, commonModule, block@{ project, checker, element ->
if (!checker.checkAccessibility(element)) {
showUnknownTypesError(element)
return@block null
}
val descriptor = element.toDescriptor() as? FunctionDescriptor
checker.existingFqNames = targetExpectedClass?.getSuperNames()?.toSet().orEmpty()
descriptor?.let {
generateFunction(
project, project,
true, true,
element, element,
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.idea.quickfix.expectactual
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.JavaDirectoryService import com.intellij.psi.JavaDirectoryService
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
@@ -23,25 +23,21 @@ import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObj
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
import org.jetbrains.kotlin.idea.core.overrideImplement.makeNotActual import org.jetbrains.kotlin.idea.core.overrideImplement.makeNotActual
import org.jetbrains.kotlin.idea.core.toDescriptor import org.jetbrains.kotlin.idea.core.toDescriptor
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.idea.util.hasInlineModifier
import org.jetbrains.kotlin.idea.util.isEffectivelyActual
import org.jetbrains.kotlin.idea.util.mustHaveValOrVar
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -111,8 +107,7 @@ internal fun KtPsiFactory.generateClassOrObject(
project: Project, project: Project,
generateExpectClass: Boolean, generateExpectClass: Boolean,
originalClass: KtClassOrObject, originalClass: KtClassOrObject,
checker: TypeAccessibilityChecker, checker: TypeAccessibilityChecker
outerClasses: List<KtClassOrObject> = emptyList()
): KtClassOrObject { ): KtClassOrObject {
val generatedClass = createClassHeaderCopyByText(originalClass) val generatedClass = createClassHeaderCopyByText(originalClass)
val context = originalClass.analyzeWithContent() val context = originalClass.analyzeWithContent()
@@ -132,7 +127,7 @@ internal fun KtPsiFactory.generateClassOrObject(
} }
if (generateExpectClass) { if (generateExpectClass) {
if (outerClasses.isEmpty()) { if (originalClass.isTopLevel()) {
generatedClass.addModifier(KtTokens.EXPECT_KEYWORD) generatedClass.addModifier(KtTokens.EXPECT_KEYWORD)
} else { } else {
generatedClass.makeNotActual() generatedClass.makeNotActual()
@@ -144,10 +139,6 @@ internal fun KtPsiFactory.generateClassOrObject(
} }
} }
val existingClasses = originalClass.declarations.asSequence().filterIsInstance<KtClassOrObject>().filter {
it.isEffectivelyActual(false)
}.toList() + generatedClass + outerClasses
val existingFqNamesWithSuperTypes = (checker.existingFqNames + superNames).toSet() val existingFqNamesWithSuperTypes = (checker.existingFqNames + superNames).toSet()
declLoop@ for (originalDeclaration in originalClass.declarations) { declLoop@ for (originalDeclaration in originalClass.declarations) {
val descriptor = originalDeclaration.toDescriptor() ?: continue val descriptor = originalDeclaration.toDescriptor() ?: continue
@@ -157,17 +148,15 @@ internal fun KtPsiFactory.generateClassOrObject(
project, project,
generateExpectClass, generateExpectClass,
originalDeclaration, originalDeclaration,
checker, checker
existingClasses
) )
is KtFunction, is KtProperty -> checker.runInContext(existingFqNamesWithSuperTypes) { is KtFunction, is KtProperty -> checker.runInContext(existingFqNamesWithSuperTypes) {
generateCallable( generateCallable(
project, project,
generateExpectClass, generateExpectClass,
originalDeclaration as KtCallableDeclaration, originalDeclaration as KtCallableDeclaration,
descriptor as CallableDescriptor, descriptor as CallableMemberDescriptor,
generatedClass, generatedClass,
existingClasses,
this this
) )
} }
@@ -180,13 +169,12 @@ internal fun KtPsiFactory.generateClassOrObject(
if (!originalProperty.hasValOrVar() || !originalProperty.hasActualModifier()) continue if (!originalProperty.hasValOrVar() || !originalProperty.hasActualModifier()) continue
val descriptor = originalProperty.toDescriptor() as? PropertyDescriptor ?: continue val descriptor = originalProperty.toDescriptor() as? PropertyDescriptor ?: continue
checker.runInContext(existingFqNamesWithSuperTypes) { checker.runInContext(existingFqNamesWithSuperTypes) {
val generatedProperty = generateProperty( val generatedProperty = generateCallable(
project, project,
generateExpectClass, generateExpectClass,
originalProperty, originalProperty,
descriptor, descriptor,
generatedClass, generatedClass,
outerClasses,
this this
) )
generatedClass.addDeclaration(generatedProperty) generatedClass.addDeclaration(generatedProperty)
@@ -202,13 +190,12 @@ internal fun KtPsiFactory.generateClassOrObject(
val descriptor = originalPrimaryConstructor.toDescriptor() val descriptor = originalPrimaryConstructor.toDescriptor()
if (descriptor is FunctionDescriptor) { if (descriptor is FunctionDescriptor) {
checker.runInContext(existingFqNamesWithSuperTypes) { checker.runInContext(existingFqNamesWithSuperTypes) {
val expectedPrimaryConstructor = generateFunction( val expectedPrimaryConstructor = generateCallable(
project, project,
generateExpectClass, generateExpectClass,
originalPrimaryConstructor, originalPrimaryConstructor,
descriptor, descriptor,
generatedClass, generatedClass,
outerClasses,
this this
) )
generatedClass.createPrimaryConstructorIfAbsent().replace(expectedPrimaryConstructor) generatedClass.createPrimaryConstructorIfAbsent().replace(expectedPrimaryConstructor)
@@ -266,52 +253,14 @@ private val forbiddenAnnotationFqNames = setOf(
internal fun generateCallable( internal fun generateCallable(
project: Project, project: Project,
generateExpect: Boolean, generateExpect: Boolean,
originalDeclaration: KtCallableDeclaration, originalDeclaration: KtDeclaration,
descriptor: CallableDescriptor, descriptor: CallableMemberDescriptor,
generatedClass: KtClassOrObject? = null, generatedClass: KtClassOrObject? = null,
outerClasses: List<KtClassOrObject> = emptyList(),
checker: TypeAccessibilityChecker checker: TypeAccessibilityChecker
) = when (originalDeclaration) { ): KtCallableDeclaration {
is KtFunction -> generateFunction( if (generateExpect) descriptor.checkAccessibility(checker)
project,
generateExpect,
originalDeclaration,
descriptor as FunctionDescriptor,
generatedClass,
outerClasses,
checker
)
is KtProperty -> generateProperty(
project,
generateExpect,
originalDeclaration,
descriptor as PropertyDescriptor,
generatedClass,
outerClasses,
checker
)
else -> error("Unsupported operation for $originalDeclaration")
}
internal fun generateFunction(
project: Project,
generateExpect: Boolean,
originalFunction: KtFunction,
descriptor: FunctionDescriptor,
generatedClass: KtClassOrObject? = null,
outerClasses: List<KtClassOrObject> = emptyList(),
checker: TypeAccessibilityChecker
): KtFunction {
if (generateExpect) {
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
descriptor.checkTypeParameterBoundsAccessibility(accessibleClasses)
descriptor.returnType?.checkAccessibility(accessibleClasses)
descriptor.valueParameters.forEach {
it.type.checkAccessibility(accessibleClasses)
}
}
val memberChooserObject = create( val memberChooserObject = create(
originalFunction, descriptor, descriptor, originalDeclaration, descriptor, descriptor,
if (generateExpect || descriptor.modality == Modality.ABSTRACT) NO_BODY else EMPTY_OR_TEMPLATE if (generateExpect || descriptor.modality == Modality.ABSTRACT) NO_BODY else EMPTY_OR_TEMPLATE
) )
return memberChooserObject.generateMember( return memberChooserObject.generateMember(
@@ -321,35 +270,12 @@ internal fun generateFunction(
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
).apply { ).apply {
repair(generatedClass, descriptor, checker) repair(generatedClass, descriptor, checker)
} as KtFunction }
} }
internal fun generateProperty( private fun CallableMemberDescriptor.checkAccessibility(checker: TypeAccessibilityChecker) {
project: Project, val errors = checker.incorrectTypes(this).ifEmpty { return }
generateExpect: Boolean, throw KotlinTypeInaccessibleException(errors.toSet())
originalProperty: KtNamedDeclaration,
descriptor: PropertyDescriptor,
generatedClass: KtClassOrObject? = null,
outerClasses: List<KtClassOrObject> = emptyList(),
checker: TypeAccessibilityChecker
): KtProperty {
if (generateExpect) {
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
descriptor.checkTypeParameterBoundsAccessibility(accessibleClasses)
descriptor.type.checkAccessibility(accessibleClasses)
}
val memberChooserObject = create(
originalProperty, descriptor, descriptor,
if (generateExpect || descriptor.modality == Modality.ABSTRACT) NO_BODY else EMPTY_OR_TEMPLATE
)
return memberChooserObject.generateMember(
targetClass = generatedClass,
copyDoc = true,
project = project,
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
).apply {
repair(generatedClass, descriptor, checker)
} as KtProperty
} }
private fun KtCallableDeclaration.repair( private fun KtCallableDeclaration.repair(
@@ -383,54 +309,9 @@ private fun AnnotationDescriptor.isValidInModule(checker: TypeAccessibilityCheck
return fqName !in forbiddenAnnotationFqNames && checker.checkAccessibility(type) return fqName !in forbiddenAnnotationFqNames && checker.checkAccessibility(type)
} }
private fun CallableMemberDescriptor.checkTypeParameterBoundsAccessibility(accessibleClasses: List<KtClassOrObject>) { class KotlinTypeInaccessibleException(fqNames: Collection<FqName?>) : Exception() {
typeParameters.forEach { typeParameter -> override val message: String =
typeParameter.upperBounds.forEach { upperBound -> "${StringUtil.pluralize("Type", fqNames.size)} ${fqNames.joinToString()} is not accessible from common code"
upperBound.checkAccessibility(accessibleClasses)
}
}
}
private fun KotlinType.checkAccessibility(accessibleClasses: List<KtClassOrObject>) {
for (argument in arguments) {
if (argument.isStarProjection) continue
argument.type.checkAccessibility(accessibleClasses)
}
val classifierDescriptor = constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters ?: return
val moduleDescriptor = classifierDescriptor.module
if (moduleDescriptor.platform.isCommon()) {
// Common classes are Ok; unfortunately this check does not work correctly for simple (non-expect) classes from common module
return
}
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(classifierDescriptor)
if (declaration?.module?.platform?.isCommon() == true) {
// Common classes are Ok again
return
}
val implementedDescriptors = moduleDescriptor.implementedDescriptors
if (implementedDescriptors.isEmpty()) {
// This happens now if we are not in sources, in this case yet we cannot answer question about accessibility
// Very rude check about JDK classes
if (!classifierDescriptor.fqNameSafe.toString().startsWith("java.")) return
}
if (implementedDescriptors.any { it.hasDeclarationOf(classifierDescriptor) }) {
// Platform classes with expected class are also Ok
return
}
accessibleClasses.forEach {
if (classifierDescriptor.name == it.nameAsName) return
}
if (this is AbbreviatedType) {
// For type aliases without expected class, check expansions instead
expandedType.checkAccessibility(accessibleClasses)
} else {
throw KotlinTypeInaccessibleException(this)
}
}
class KotlinTypeInaccessibleException(val type: KotlinType) : Exception() {
override val message: String
get() = "Type ${type.getJetTypeFqName(true)} is not accessible from common code"
} }
fun KtNamedDeclaration.isAlwaysActual(): Boolean = safeAs<KtParameter>()?.parent?.parent?.safeAs<KtPrimaryConstructor>() fun KtNamedDeclaration.isAlwaysActual(): Boolean = safeAs<KtParameter>()?.parent?.parent?.safeAs<KtPrimaryConstructor>()