ExpectActualUtils: add type accessibility check
This commit is contained in:
@@ -11,6 +11,7 @@ import com.intellij.openapi.application.ApplicationManager
|
|||||||
import com.intellij.openapi.editor.Editor
|
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 com.intellij.openapi.ui.showOkNoDialog
|
||||||
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.FunctionDescriptor
|
||||||
@@ -24,7 +25,10 @@ import org.jetbrains.kotlin.idea.core.overrideImplement.makeActual
|
|||||||
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.core.util.DescriptorMemberChooserObject
|
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
|
||||||
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
|
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHint
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.renderTrimmed
|
||||||
import org.jetbrains.kotlin.idea.util.allowedValOrVar
|
import org.jetbrains.kotlin.idea.util.allowedValOrVar
|
||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.idea.util.liftToExpected
|
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||||
@@ -34,6 +38,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
sealed class CreateExpectedFix<D : KtNamedDeclaration>(
|
sealed class CreateExpectedFix<D : KtNamedDeclaration>(
|
||||||
declaration: D,
|
declaration: D,
|
||||||
@@ -111,17 +116,36 @@ class CreateExpectedClassFix(
|
|||||||
outerExpectedClass: KtClassOrObject?,
|
outerExpectedClass: KtClassOrObject?,
|
||||||
commonModule: Module
|
commonModule: Module
|
||||||
) : CreateExpectedFix<KtClassOrObject>(klass, outerExpectedClass, commonModule, block@{ project, element ->
|
) : CreateExpectedFix<KtClassOrObject>(klass, outerExpectedClass, commonModule, block@{ project, element ->
|
||||||
val originalElements = element.collectDeclarations(false).filter(KtDeclaration::canAddActualModifier).toList()
|
val originalElements = element.collectDeclarations(false).toList()
|
||||||
val members = originalElements.filterNot(KtDeclaration::isAlwaysActual)
|
val existingClasses = findClasses(originalElements + klass)
|
||||||
|
|
||||||
|
val (members, declarationsWithNonExistentClasses) = originalElements.filterNot(KtNamedDeclaration::isAlwaysActual).partition {
|
||||||
|
it.checkTypeAccessibilityInModule(commonModule, existingClasses)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showUnknownTypesDialog(project, declarationsWithNonExistentClasses)) return@block null
|
||||||
|
|
||||||
val selectedElements = when {
|
val selectedElements = when {
|
||||||
members.all(KtDeclaration::hasActualModifier) -> originalElements
|
members.all(KtDeclaration::hasActualModifier) -> originalElements - declarationsWithNonExistentClasses
|
||||||
ApplicationManager.getApplication().isUnitTestMode -> members.filter(KtDeclaration::hasActualModifier)
|
ApplicationManager.getApplication().isUnitTestMode -> members.filter(KtDeclaration::hasActualModifier)
|
||||||
else -> {
|
else -> {
|
||||||
val prefix = klass.fqName?.asString()?.plus(".") ?: ""
|
val prefix = klass.fqName?.asString()?.plus(".") ?: ""
|
||||||
chooseMembers(project, members, prefix) ?: return@block null
|
chooseMembers(project, members, prefix) ?: return@block null
|
||||||
}
|
}
|
||||||
|
}.let { selectedElements ->
|
||||||
|
val selectedClasses = findClasses(selectedElements)
|
||||||
|
if (selectedClasses != existingClasses) {
|
||||||
|
val (resultDeclarations, withErrors) = selectedElements.partition {
|
||||||
|
it.checkTypeAccessibilityInModule(commonModule, selectedClasses)
|
||||||
|
}
|
||||||
|
if (!showUnknownTypesDialog(project, withErrors)) return@block null
|
||||||
|
resultDeclarations
|
||||||
|
} else
|
||||||
|
selectedElements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (originalElements.isNotEmpty()) {
|
if (originalElements.isNotEmpty()) {
|
||||||
project.executeWriteCommand("Repair actual members") {
|
project.executeWriteCommand("Repair actual members") {
|
||||||
repairActualModifiers(originalElements, selectedElements)
|
repairActualModifiers(originalElements, selectedElements)
|
||||||
@@ -131,6 +155,30 @@ class CreateExpectedClassFix(
|
|||||||
generateClassOrObject(project, true, element, listOfNotNull(outerExpectedClass))
|
generateClassOrObject(project, true, element, listOfNotNull(outerExpectedClass))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
private fun findClasses(elements: List<KtNamedDeclaration>): HashSet<String> {
|
||||||
|
return elements.filterIsInstance<KtClassOrObject>().mapNotNull { it.fqName?.asString() }.toHashSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUnknownTypesDialog(project: Project, declarationsWithNonExistentClasses: List<KtNamedDeclaration>): Boolean =
|
||||||
|
declarationsWithNonExistentClasses.isEmpty() || showOkNoDialog(
|
||||||
|
"Unknown types",
|
||||||
|
declarationsWithNonExistentClasses.joinToString(prefix = "These declarations cannot be transformed:\n", separator = "\n") {
|
||||||
|
it.renderTrimmed()
|
||||||
|
},
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun showUnknownTypesError(element: KtNamedDeclaration) {
|
||||||
|
element.findExistingEditor()?.let { editor ->
|
||||||
|
showErrorHint(
|
||||||
|
element.project,
|
||||||
|
editor,
|
||||||
|
"You cannot create the expect declaration from:\n${element.renderTrimmed()}",
|
||||||
|
"Unknown types"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KtDeclaration.canAddActualModifier() = when (this) {
|
private fun KtDeclaration.canAddActualModifier() = when (this) {
|
||||||
is KtEnumEntry, is KtClassInitializer -> false
|
is KtEnumEntry, is KtClassInitializer -> false
|
||||||
is KtParameter -> hasValOrVar()
|
is KtParameter -> hasValOrVar()
|
||||||
@@ -141,7 +189,7 @@ private fun KtDeclaration.canAddActualModifier() = when (this) {
|
|||||||
/***
|
/***
|
||||||
* @return null if close without OK
|
* @return null if close without OK
|
||||||
*/
|
*/
|
||||||
private fun chooseMembers(project: Project, collection: Collection<KtDeclaration>, prefixToRemove: String): List<KtDeclaration>? {
|
private fun chooseMembers(project: Project, collection: Collection<KtNamedDeclaration>, prefixToRemove: String): List<KtNamedDeclaration>? {
|
||||||
val classMembers = collection.mapNotNull {
|
val classMembers = collection.mapNotNull {
|
||||||
it.resolveToDescriptorIfAny()?.let { descriptor -> Member(prefixToRemove, it, descriptor) }
|
it.resolveToDescriptorIfAny()?.let { descriptor -> Member(prefixToRemove, it, descriptor) }
|
||||||
}
|
}
|
||||||
@@ -158,9 +206,9 @@ private fun chooseMembers(project: Project, collection: Collection<KtDeclaration
|
|||||||
).run {
|
).run {
|
||||||
title = "Choose actual members"
|
title = "Choose actual members"
|
||||||
setCopyJavadocVisible(false)
|
setCopyJavadocVisible(false)
|
||||||
selectElements(classMembers.filter { filter((it.element as KtDeclaration)) }.toTypedArray())
|
selectElements(classMembers.filter { filter((it.element as KtNamedDeclaration)) }.toTypedArray())
|
||||||
show()
|
show()
|
||||||
if (!isOK) null else selectedElements?.map { it.element as KtDeclaration }.orEmpty()
|
if (!isOK) null else selectedElements?.map { it.element as KtNamedDeclaration }.orEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,19 +221,27 @@ private class Member(val prefix: String, element: KtElement, descriptor: Declara
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtClassOrObject.collectDeclarations(withSelf: Boolean = true): Sequence<KtDeclaration> {
|
private fun KtClassOrObject.collectDeclarations(withSelf: Boolean = true): Sequence<KtNamedDeclaration> {
|
||||||
val thisSequence = if (withSelf) sequenceOf(this) else emptySequence()
|
val thisSequence: Sequence<KtNamedDeclaration> = if (withSelf) sequenceOf(this) else emptySequence()
|
||||||
val primaryConstructorSequence = primaryConstructorParameters.asSequence() + primaryConstructor.let {
|
val primaryConstructorSequence: Sequence<KtNamedDeclaration> = primaryConstructorParameters.asSequence() + primaryConstructor.let {
|
||||||
if (it != null) sequenceOf(it) else emptySequence()
|
if (it != null) sequenceOf(it) else emptySequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
return thisSequence + primaryConstructorSequence + declarations.asSequence().flatMap {
|
return thisSequence + primaryConstructorSequence + declarations.asSequence().flatMap {
|
||||||
if (it is KtClassOrObject) it.collectDeclarations() else sequenceOf(it)
|
if (it.canAddActualModifier())
|
||||||
|
when (it) {
|
||||||
|
is KtClassOrObject -> it.collectDeclarations()
|
||||||
|
is KtNamedDeclaration -> sequenceOf(it)
|
||||||
|
else -> emptySequence()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
emptySequence()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun repairActualModifiers(
|
private fun repairActualModifiers(
|
||||||
originalElements: Collection<KtDeclaration>,
|
originalElements: Collection<KtNamedDeclaration>,
|
||||||
selectedElements: Collection<KtDeclaration>
|
selectedElements: Collection<KtNamedDeclaration>
|
||||||
) {
|
) {
|
||||||
if (originalElements.size == selectedElements.size)
|
if (originalElements.size == selectedElements.size)
|
||||||
for (original in originalElements) {
|
for (original in originalElements) {
|
||||||
@@ -205,7 +261,7 @@ private tailrec fun KtDeclaration.makeActualWithParents() {
|
|||||||
containingClassOrObject?.takeUnless(KtDeclaration::hasActualModifier)?.makeActualWithParents()
|
containingClassOrObject?.takeUnless(KtDeclaration::hasActualModifier)?.makeActualWithParents()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtDeclaration.isAlwaysActual(): Boolean = when (this) {
|
private fun KtNamedDeclaration.isAlwaysActual(): Boolean = when (this) {
|
||||||
is KtPrimaryConstructor -> this
|
is KtPrimaryConstructor -> this
|
||||||
is KtParameter -> (parent as? KtParameterList)?.parent as? KtPrimaryConstructor
|
is KtParameter -> (parent as? KtParameterList)?.parent as? KtPrimaryConstructor
|
||||||
else -> null
|
else -> null
|
||||||
@@ -215,7 +271,11 @@ class CreateExpectedPropertyFix(
|
|||||||
property: KtNamedDeclaration,
|
property: KtNamedDeclaration,
|
||||||
targetExpectedClass: KtClassOrObject?,
|
targetExpectedClass: KtClassOrObject?,
|
||||||
commonModule: Module
|
commonModule: Module
|
||||||
) : CreateExpectedFix<KtNamedDeclaration>(property, targetExpectedClass, commonModule, { project, element ->
|
) : CreateExpectedFix<KtNamedDeclaration>(property, targetExpectedClass, commonModule, block@{ project, element ->
|
||||||
|
if (!element.checkTypeAccessibilityInModule(commonModule)) {
|
||||||
|
showUnknownTypesError(element)
|
||||||
|
return@block null
|
||||||
|
}
|
||||||
val descriptor = element.toDescriptor() as? PropertyDescriptor
|
val descriptor = element.toDescriptor() as? PropertyDescriptor
|
||||||
descriptor?.let { generateProperty(project, true, element, descriptor, targetExpectedClass) }
|
descriptor?.let { generateProperty(project, true, element, descriptor, targetExpectedClass) }
|
||||||
})
|
})
|
||||||
@@ -224,7 +284,11 @@ class CreateExpectedFunctionFix(
|
|||||||
function: KtFunction,
|
function: KtFunction,
|
||||||
targetExpectedClass: KtClassOrObject?,
|
targetExpectedClass: KtClassOrObject?,
|
||||||
commonModule: Module
|
commonModule: Module
|
||||||
) : CreateExpectedFix<KtFunction>(function, targetExpectedClass, commonModule, { project, element ->
|
) : CreateExpectedFix<KtFunction>(function, targetExpectedClass, commonModule, block@{ project, element ->
|
||||||
|
if (!element.checkTypeAccessibilityInModule(commonModule)) {
|
||||||
|
showUnknownTypesError(element)
|
||||||
|
return@block null
|
||||||
|
}
|
||||||
val descriptor = element.toDescriptor() as? FunctionDescriptor
|
val descriptor = element.toDescriptor() as? FunctionDescriptor
|
||||||
descriptor?.let { generateFunction(project, true, element, descriptor, targetExpectedClass) }
|
descriptor?.let { generateFunction(project, true, element, descriptor, targetExpectedClass) }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,8 +8,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.psi.JavaDirectoryService
|
import com.intellij.psi.JavaDirectoryService
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.isTestModule
|
||||||
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
|
||||||
@@ -24,6 +26,8 @@ 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.project.platform
|
||||||
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
|
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||||
import org.jetbrains.kotlin.idea.util.*
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
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.js.descriptorUtils.getJetTypeFqName
|
||||||
@@ -36,6 +40,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
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.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.types.AbbreviatedType
|
import org.jetbrains.kotlin.types.AbbreviatedType
|
||||||
@@ -122,7 +127,7 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
val superType = context[BindingContext.TYPE, originalEntry.typeReference]
|
val superType = context[BindingContext.TYPE, originalEntry.typeReference]
|
||||||
val superClassDescriptor = superType?.constructor?.declarationDescriptor as? ClassDescriptor ?: return@forEach
|
val superClassDescriptor = superType?.constructor?.declarationDescriptor as? ClassDescriptor ?: return@forEach
|
||||||
if (superClassDescriptor.kind == ClassKind.CLASS || superClassDescriptor.kind == ClassKind.ENUM_CLASS) {
|
if (superClassDescriptor.kind == ClassKind.CLASS || superClassDescriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
val entryText = IdeDescriptorRenderers.SOURCE_CODE.renderType(superType) ?: return@forEach
|
val entryText = IdeDescriptorRenderers.SOURCE_CODE.renderType(superType)
|
||||||
val newGeneratedEntry = if (generateExpectClass) {
|
val newGeneratedEntry = if (generateExpectClass) {
|
||||||
createSuperTypeEntry(entryText)
|
createSuperTypeEntry(entryText)
|
||||||
} else {
|
} else {
|
||||||
@@ -152,20 +157,22 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val existingClasses = originalClass.declarations.asSequence().filterIsInstance<KtClassOrObject>().filter {
|
||||||
|
it.isEffectivelyActual(false)
|
||||||
|
}.toList() + generatedClass + outerClasses
|
||||||
|
|
||||||
declLoop@ for (originalDeclaration in originalClass.declarations) {
|
declLoop@ for (originalDeclaration in originalClass.declarations) {
|
||||||
val descriptor = originalDeclaration.toDescriptor() ?: continue
|
val descriptor = originalDeclaration.toDescriptor() ?: continue
|
||||||
if (generateExpectClass && !originalDeclaration.isEffectivelyActual(false)) continue
|
if (generateExpectClass && !originalDeclaration.isEffectivelyActual(false)) continue
|
||||||
val generatedDeclaration: KtDeclaration = when (originalDeclaration) {
|
val generatedDeclaration: KtDeclaration = when (originalDeclaration) {
|
||||||
is KtClassOrObject -> {
|
is KtClassOrObject -> generateClassOrObject(project, generateExpectClass, originalDeclaration, existingClasses)
|
||||||
generateClassOrObject(project, generateExpectClass, originalDeclaration, outerClasses + generatedClass)
|
|
||||||
}
|
|
||||||
is KtCallableDeclaration -> {
|
is KtCallableDeclaration -> {
|
||||||
when (originalDeclaration) {
|
when (originalDeclaration) {
|
||||||
is KtFunction -> generateFunction(
|
is KtFunction -> generateFunction(
|
||||||
project, generateExpectClass, originalDeclaration, descriptor as FunctionDescriptor, generatedClass, outerClasses
|
project, generateExpectClass, originalDeclaration, descriptor as FunctionDescriptor, generatedClass, existingClasses
|
||||||
)
|
)
|
||||||
is KtProperty -> generateProperty(
|
is KtProperty -> generateProperty(
|
||||||
project, generateExpectClass, originalDeclaration, descriptor as PropertyDescriptor, generatedClass, outerClasses
|
project, generateExpectClass, originalDeclaration, descriptor as PropertyDescriptor, generatedClass, existingClasses
|
||||||
)
|
)
|
||||||
else -> continue@declLoop
|
else -> continue@declLoop
|
||||||
}
|
}
|
||||||
@@ -310,3 +317,28 @@ class KotlinTypeInaccessibleException(val type: KotlinType) : Exception() {
|
|||||||
override val message: String
|
override val message: String
|
||||||
get() = "Type ${type.getJetTypeFqName(true)} is not accessible from common code"
|
get() = "Type ${type.getJetTypeFqName(true)} is not accessible from common code"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtNamedDeclaration.checkTypeAccessibilityInModule(module: Module, existedClasses: Set<String> = emptySet()): Boolean {
|
||||||
|
if (hasPrivateModifier()) return false
|
||||||
|
val types = when (this) {
|
||||||
|
is KtClassOrObject -> return fqName?.canFindClassInModule(project, module, existedClasses) == true
|
||||||
|
is KtCallableDeclaration -> {
|
||||||
|
val descriptor = descriptor?.safeAs<CallableDescriptor>() ?: return false
|
||||||
|
val returnType = descriptor.returnType ?: return false
|
||||||
|
(listOfNotNull(descriptor.extensionReceiverParameter) + descriptor.valueParameters).map { it.type } + returnType
|
||||||
|
}
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val project = project
|
||||||
|
return types.all { it.fqName?.canFindClassInModule(project, module, existedClasses) ?: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
val KotlinType.fqName: FqName? get() = constructor.declarationDescriptor?.fqNameOrNull()
|
||||||
|
|
||||||
|
private fun FqName.canFindClassInModule(project: Project, module: Module, existedClasses: Set<String>): Boolean {
|
||||||
|
val name = asString()
|
||||||
|
return name in existedClasses || KotlinFullClassNameIndex.getInstance()[
|
||||||
|
name, project, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, module.isTestModule)
|
||||||
|
].isNotEmpty()
|
||||||
|
}
|
||||||
@@ -29,6 +29,8 @@ fun KtCallExpression.replaceOrCreateTypeArgumentList(newTypeArgumentList: KtType
|
|||||||
|
|
||||||
fun KtModifierListOwner.hasInlineModifier() = hasModifier(KtTokens.INLINE_KEYWORD)
|
fun KtModifierListOwner.hasInlineModifier() = hasModifier(KtTokens.INLINE_KEYWORD)
|
||||||
|
|
||||||
|
fun KtModifierListOwner.hasPrivateModifier() = hasModifier(KtTokens.PRIVATE_KEYWORD)
|
||||||
|
|
||||||
fun KtPrimaryConstructor.allowedValOrVar(): Boolean = containingClass()?.let {
|
fun KtPrimaryConstructor.allowedValOrVar(): Boolean = containingClass()?.let {
|
||||||
it.isAnnotation() || it.hasInlineModifier()
|
it.isAnnotation() || it.hasInlineModifier()
|
||||||
} ?: false
|
} ?: false
|
||||||
|
|||||||
Reference in New Issue
Block a user