ExpectActualUtils: add type arguments accessibility check
This commit is contained in:
@@ -133,7 +133,7 @@ class CreateExpectedClassFix(
|
|||||||
chooseMembers(project, members, prefix) ?: return@block null
|
chooseMembers(project, members, prefix) ?: return@block null
|
||||||
}
|
}
|
||||||
}.let { selectedElements ->
|
}.let { selectedElements ->
|
||||||
val selectedClasses = findClasses(selectedElements)
|
val selectedClasses = findClasses(selectedElements + klass)
|
||||||
if (selectedClasses != existingClasses) {
|
if (selectedClasses != existingClasses) {
|
||||||
val (resultDeclarations, withErrors) = selectedElements.partition {
|
val (resultDeclarations, withErrors) = selectedElements.partition {
|
||||||
it.checkTypeAccessibilityInModule(commonModule, selectedClasses)
|
it.checkTypeAccessibilityInModule(commonModule, selectedClasses)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ 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 com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||||
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.project.isTestModule
|
||||||
@@ -45,6 +46,7 @@ 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
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjection
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
fun createFileForDeclaration(module: Module, declaration: KtNamedDeclaration): KtFile? {
|
fun createFileForDeclaration(module: Module, declaration: KtNamedDeclaration): KtFile? {
|
||||||
@@ -318,20 +320,34 @@ class KotlinTypeInaccessibleException(val type: KotlinType) : Exception() {
|
|||||||
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 {
|
fun DeclarationDescriptor.checkTypeAccessibilityInModule(
|
||||||
if (hasPrivateModifier()) return false
|
project: Project,
|
||||||
val types = when (this) {
|
module: Module,
|
||||||
is KtClassOrObject -> return fqName?.canFindClassInModule(project, module, existedClasses) == true
|
existedClasses: Set<String> = emptySet()
|
||||||
is KtCallableDeclaration -> {
|
): Boolean = collectAllTypes().all { it?.canFindClassInModule(project, module, existedClasses) == true }
|
||||||
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
|
private fun DeclarationDescriptor.collectAllTypes(): Sequence<FqName?> {
|
||||||
return types.all { it.fqName?.canFindClassInModule(project, module, existedClasses) ?: false }
|
return when (this) {
|
||||||
|
is ClassDescriptor -> declaredTypeParameters.asSequence().flatMap(DeclarationDescriptor::collectAllTypes)
|
||||||
|
is CallableDescriptor -> {
|
||||||
|
val returnType = returnType ?: return sequenceOf(null)
|
||||||
|
returnType.collectAllTypes() + allParameters.asSequence().map { it.type }.flatMap(KotlinType::collectAllTypes)
|
||||||
|
}
|
||||||
|
is TypeParameterDescriptor -> {
|
||||||
|
val upperBounds = upperBounds
|
||||||
|
if (upperBounds.isEmpty()) sequenceOf(fqNameOrNull())
|
||||||
|
else upperBounds.asSequence().flatMap(KotlinType::collectAllTypes)
|
||||||
|
}
|
||||||
|
else -> emptySequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinType.collectAllTypes(): Sequence<FqName?> = sequenceOf(fqName) + arguments.asSequence()
|
||||||
|
.map(TypeProjection::getType)
|
||||||
|
.flatMap(KotlinType::collectAllTypes)
|
||||||
|
|
||||||
|
fun KtNamedDeclaration.checkTypeAccessibilityInModule(module: Module, existedClasses: Set<String> = emptySet()): Boolean {
|
||||||
|
return !hasPrivateModifier() && descriptor?.checkTypeAccessibilityInModule(project, module, existedClasses) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
val KotlinType.fqName: FqName? get() = constructor.declarationDescriptor?.fqNameOrNull()
|
val KotlinType.fqName: FqName? get() = constructor.declarationDescriptor?.fqNameOrNull()
|
||||||
|
|||||||
Reference in New Issue
Block a user