ExpectActualUtils: should add annotations
This commit is contained in:
@@ -61,10 +61,10 @@ class AddActualFix(
|
|||||||
val actualDeclaration = when (missedDeclaration) {
|
val actualDeclaration = when (missedDeclaration) {
|
||||||
is KtClassOrObject -> factory.generateClassOrObject(project, false, missedDeclaration, module, listOf(element))
|
is KtClassOrObject -> factory.generateClassOrObject(project, false, missedDeclaration, module, listOf(element))
|
||||||
is KtFunction -> missedDeclaration.toDescriptor()?.safeAs<FunctionDescriptor>()?.let {
|
is KtFunction -> missedDeclaration.toDescriptor()?.safeAs<FunctionDescriptor>()?.let {
|
||||||
generateFunction(project, false, missedDeclaration, it, element)
|
generateFunction(project, false, missedDeclaration, it, element, targetModule = module)
|
||||||
}
|
}
|
||||||
is KtProperty -> missedDeclaration.toDescriptor()?.safeAs<PropertyDescriptor>()?.let {
|
is KtProperty -> missedDeclaration.toDescriptor()?.safeAs<PropertyDescriptor>()?.let {
|
||||||
generateProperty(project, false, missedDeclaration, it, element)
|
generateProperty(project, false, missedDeclaration, it, element, targetModule = module)
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
} ?: continue
|
} ?: continue
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class CreateActualPropertyFix(
|
|||||||
actualPlatform: TargetPlatform
|
actualPlatform: TargetPlatform
|
||||||
) : CreateActualFix<KtProperty>(property, actualModule, actualPlatform, { project, element ->
|
) : CreateActualFix<KtProperty>(property, actualModule, actualPlatform, { project, element ->
|
||||||
val descriptor = element.toDescriptor() as? PropertyDescriptor
|
val descriptor = element.toDescriptor() as? PropertyDescriptor
|
||||||
descriptor?.let { generateProperty(project, false, element, descriptor) }
|
descriptor?.let { generateProperty(project, false, element, descriptor, targetModule = actualModule) }
|
||||||
})
|
})
|
||||||
|
|
||||||
class CreateActualFunctionFix(
|
class CreateActualFunctionFix(
|
||||||
@@ -105,6 +105,6 @@ class CreateActualFunctionFix(
|
|||||||
actualPlatform: TargetPlatform
|
actualPlatform: TargetPlatform
|
||||||
) : CreateActualFix<KtFunction>(function, actualModule, actualPlatform, { project, element ->
|
) : CreateActualFix<KtFunction>(function, actualModule, actualPlatform, { project, element ->
|
||||||
val descriptor = element.toDescriptor() as? FunctionDescriptor
|
val descriptor = element.toDescriptor() as? FunctionDescriptor
|
||||||
descriptor?.let { generateFunction(project, false, element, descriptor) }
|
descriptor?.let { generateFunction(project, false, element, descriptor, targetModule = actualModule) }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,8 @@ class CreateExpectedPropertyFix(
|
|||||||
element,
|
element,
|
||||||
descriptor,
|
descriptor,
|
||||||
targetExpectedClass,
|
targetExpectedClass,
|
||||||
existingFqNames = targetExpectedClass?.getSuperNames().orEmpty()
|
existingFqNames = targetExpectedClass?.getSuperNames()?.toSet().orEmpty(),
|
||||||
|
targetModule = commonModule
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -316,7 +317,8 @@ class CreateExpectedFunctionFix(
|
|||||||
element,
|
element,
|
||||||
descriptor,
|
descriptor,
|
||||||
targetExpectedClass,
|
targetExpectedClass,
|
||||||
existingFqNames = targetExpectedClass?.getSuperNames().orEmpty()
|
existingFqNames = targetExpectedClass?.getSuperNames()?.toSet().orEmpty(),
|
||||||
|
targetModule = commonModule
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.intellij.psi.JavaDirectoryService
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
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
|
||||||
import org.jetbrains.kotlin.idea.caches.project.toDescriptor
|
import org.jetbrains.kotlin.idea.caches.project.toDescriptor
|
||||||
@@ -46,6 +47,7 @@ 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.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
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.types.TypeProjection
|
||||||
@@ -133,14 +135,13 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
if (generatedClass.isAnnotation()) {
|
generatedClass.annotationEntries.zip(originalClass.annotationEntries).forEach { (generatedEntry, originalEntry) ->
|
||||||
generatedClass.annotationEntries.zip(originalClass.annotationEntries).forEach { (generatedEntry, originalEntry) ->
|
val annotationDescriptor = context.get(BindingContext.ANNOTATION, originalEntry)
|
||||||
val annotationDescriptor = context.get(BindingContext.ANNOTATION, originalEntry) ?: return@forEach
|
if (annotationDescriptor?.isValidInModule(targetModule, existingFqNames, project) != true) {
|
||||||
if (annotationDescriptor.fqName in forbiddenAnnotationFqNames) {
|
generatedEntry.delete()
|
||||||
generatedEntry.delete()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generateExpectClass) {
|
if (generateExpectClass) {
|
||||||
if (outerClasses.isEmpty()) {
|
if (outerClasses.isEmpty()) {
|
||||||
generatedClass.addModifier(KtTokens.EXPECT_KEYWORD)
|
generatedClass.addModifier(KtTokens.EXPECT_KEYWORD)
|
||||||
@@ -170,29 +171,26 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
existingClasses,
|
existingClasses,
|
||||||
existingFqNames
|
existingFqNames
|
||||||
)
|
)
|
||||||
is KtCallableDeclaration -> {
|
is KtFunction -> generateFunction(
|
||||||
when (originalDeclaration) {
|
project,
|
||||||
is KtFunction -> generateFunction(
|
generateExpectClass,
|
||||||
project,
|
originalDeclaration,
|
||||||
generateExpectClass,
|
descriptor as FunctionDescriptor,
|
||||||
originalDeclaration,
|
generatedClass,
|
||||||
descriptor as FunctionDescriptor,
|
existingClasses,
|
||||||
generatedClass,
|
existingFqNames + superNames,
|
||||||
existingClasses,
|
targetModule
|
||||||
existingFqNames + superNames
|
)
|
||||||
)
|
is KtProperty -> generateProperty(
|
||||||
is KtProperty -> generateProperty(
|
project,
|
||||||
project,
|
generateExpectClass,
|
||||||
generateExpectClass,
|
originalDeclaration,
|
||||||
originalDeclaration,
|
descriptor as PropertyDescriptor,
|
||||||
descriptor as PropertyDescriptor,
|
generatedClass,
|
||||||
generatedClass,
|
existingClasses,
|
||||||
existingClasses,
|
existingFqNames + superNames,
|
||||||
existingFqNames + superNames
|
targetModule
|
||||||
)
|
)
|
||||||
else -> continue@declLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> continue@declLoop
|
else -> continue@declLoop
|
||||||
}
|
}
|
||||||
generatedClass.addDeclaration(generatedDeclaration)
|
generatedClass.addDeclaration(generatedDeclaration)
|
||||||
@@ -208,7 +206,8 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
descriptor,
|
descriptor,
|
||||||
generatedClass,
|
generatedClass,
|
||||||
outerClasses,
|
outerClasses,
|
||||||
existingFqNames + superNames
|
existingFqNames + superNames,
|
||||||
|
targetModule
|
||||||
)
|
)
|
||||||
generatedClass.addDeclaration(generatedProperty)
|
generatedClass.addDeclaration(generatedProperty)
|
||||||
}
|
}
|
||||||
@@ -228,7 +227,8 @@ internal fun KtPsiFactory.generateClassOrObject(
|
|||||||
descriptor,
|
descriptor,
|
||||||
generatedClass,
|
generatedClass,
|
||||||
outerClasses,
|
outerClasses,
|
||||||
existingFqNames + superNames
|
existingFqNames + superNames,
|
||||||
|
targetModule
|
||||||
)
|
)
|
||||||
generatedClass.createPrimaryConstructorIfAbsent().replace(expectedPrimaryConstructor)
|
generatedClass.createPrimaryConstructorIfAbsent().replace(expectedPrimaryConstructor)
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,8 @@ internal fun generateFunction(
|
|||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
generatedClass: KtClassOrObject? = null,
|
generatedClass: KtClassOrObject? = null,
|
||||||
outerClasses: List<KtClassOrObject> = emptyList(),
|
outerClasses: List<KtClassOrObject> = emptyList(),
|
||||||
existingFqNames: Collection<String> = emptySet()
|
existingFqNames: Set<String> = emptySet(),
|
||||||
|
targetModule: Module
|
||||||
): KtFunction {
|
): KtFunction {
|
||||||
if (generateExpect) {
|
if (generateExpect) {
|
||||||
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
|
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
|
||||||
@@ -312,7 +313,9 @@ internal fun generateFunction(
|
|||||||
copyDoc = true,
|
copyDoc = true,
|
||||||
project = project,
|
project = project,
|
||||||
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
|
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
|
||||||
).also { if (generatedClass != null) it.repairOverride(descriptor, existingFqNames) } as KtFunction
|
).apply {
|
||||||
|
repair(generatedClass, descriptor, existingFqNames, targetModule, project)
|
||||||
|
} as KtFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun generateProperty(
|
internal fun generateProperty(
|
||||||
@@ -322,7 +325,8 @@ internal fun generateProperty(
|
|||||||
descriptor: PropertyDescriptor,
|
descriptor: PropertyDescriptor,
|
||||||
generatedClass: KtClassOrObject? = null,
|
generatedClass: KtClassOrObject? = null,
|
||||||
outerClasses: List<KtClassOrObject> = emptyList(),
|
outerClasses: List<KtClassOrObject> = emptyList(),
|
||||||
existingFqNames: Collection<String> = emptySet()
|
existingFqNames: Set<String> = emptySet(),
|
||||||
|
targetModule: Module
|
||||||
): KtProperty {
|
): KtProperty {
|
||||||
if (generateExpect) {
|
if (generateExpect) {
|
||||||
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
|
val accessibleClasses = outerClasses + listOfNotNull(generatedClass)
|
||||||
@@ -338,10 +342,23 @@ internal fun generateProperty(
|
|||||||
copyDoc = true,
|
copyDoc = true,
|
||||||
project = project,
|
project = project,
|
||||||
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
|
mode = if (generateExpect) MemberGenerateMode.EXPECT else MemberGenerateMode.ACTUAL
|
||||||
).also { if (generatedClass != null) it.repairOverride(descriptor, existingFqNames) } as KtProperty
|
).apply {
|
||||||
|
repair(generatedClass, descriptor, existingFqNames, targetModule, project)
|
||||||
|
} as KtProperty
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtCallableDeclaration.repairOverride(descriptor: CallableDescriptor, existingFqNames: Collection<String>) {
|
private fun KtCallableDeclaration.repair(
|
||||||
|
generatedClass: KtClassOrObject?,
|
||||||
|
descriptor: CallableDescriptor,
|
||||||
|
existingFqNames: Set<String>,
|
||||||
|
targetModule: Module,
|
||||||
|
project: Project
|
||||||
|
) {
|
||||||
|
if (generatedClass != null) repairOverride(descriptor, existingFqNames)
|
||||||
|
repairAnnotationEntries(descriptor, existingFqNames, targetModule, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtCallableDeclaration.repairOverride(descriptor: CallableDescriptor, existingFqNames: Set<String>) {
|
||||||
if (!hasModifier(KtTokens.OVERRIDE_KEYWORD)) return
|
if (!hasModifier(KtTokens.OVERRIDE_KEYWORD)) return
|
||||||
|
|
||||||
val superDescriptor = descriptor.overriddenDescriptors.firstOrNull()?.containingDeclaration
|
val superDescriptor = descriptor.overriddenDescriptors.firstOrNull()?.containingDeclaration
|
||||||
@@ -350,6 +367,24 @@ private fun KtCallableDeclaration.repairOverride(descriptor: CallableDescriptor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KtCallableDeclaration.repairAnnotationEntries(
|
||||||
|
descriptor: CallableDescriptor,
|
||||||
|
existingFqNames: Set<String>,
|
||||||
|
module: Module,
|
||||||
|
project: Project
|
||||||
|
) {
|
||||||
|
for (annotation in descriptor.annotations) {
|
||||||
|
if (annotation.isValidInModule(module, existingFqNames, project)) {
|
||||||
|
val entry = annotation.source.safeAs<KotlinSourceElement>()?.psi.safeAs<KtAnnotationEntry>() ?: continue
|
||||||
|
addAnnotationEntry(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AnnotationDescriptor.isValidInModule(targetModule: Module, existingFqNames: Set<String>, project: Project): Boolean {
|
||||||
|
return fqName !in forbiddenAnnotationFqNames && type.checkTypeAccessibilityInModule(project, targetModule, existingFqNames)
|
||||||
|
}
|
||||||
|
|
||||||
private fun CallableMemberDescriptor.checkTypeParameterBoundsAccessibility(accessibleClasses: List<KtClassOrObject>) {
|
private fun CallableMemberDescriptor.checkTypeParameterBoundsAccessibility(accessibleClasses: List<KtClassOrObject>) {
|
||||||
typeParameters.forEach { typeParameter ->
|
typeParameters.forEach { typeParameter ->
|
||||||
typeParameter.upperBounds.forEach { upperBound ->
|
typeParameter.upperBounds.forEach { upperBound ->
|
||||||
|
|||||||
Reference in New Issue
Block a user