ExpectActualUtils: add type arguments accessibility check

This commit is contained in:
Dmitry Gridin
2019-08-06 17:27:05 +03:00
parent 5884c65857
commit bad9459978
2 changed files with 30 additions and 14 deletions
@@ -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()