Use OverrideMemberChooserObject to generate also abstract actual decls

Relates to KT-27093 and similar problems
This commit is contained in:
Mikhail Glukhikh
2018-11-14 10:47:58 +03:00
parent 3612c2983e
commit cd041cca71
12 changed files with 80 additions and 46 deletions
@@ -186,6 +186,7 @@ interface DescriptorRendererOptions {
var withoutReturnType: Boolean
var normalizedVisibilities: Boolean
var renderDefaultVisibility: Boolean
var renderDefaultModality: Boolean
var uninferredTypeParameterAsName: Boolean
var overrideRenderingPolicy: OverrideRenderingPolicy
var valueParametersHandler: DescriptorRenderer.ValueParametersHandler
@@ -478,17 +478,33 @@ internal class DescriptorRendererImpl(
builder.append(renderKeyword(visibility.displayName)).append(" ")
}
private fun renderModality(modality: Modality, builder: StringBuilder) {
private fun renderModality(modality: Modality, builder: StringBuilder, defaultModality: Modality) {
if (!renderDefaultModality && modality == defaultModality) return
renderModifier(builder, DescriptorRendererModifier.MODALITY in modifiers, modality.name.toLowerCase())
}
private fun MemberDescriptor.implicitModalityWithoutExtensions(): Modality {
if (this is ClassDescriptor) {
return if (kind == ClassKind.INTERFACE) Modality.ABSTRACT else Modality.FINAL
}
val containingClassDescriptor = containingDeclaration as? ClassDescriptor ?: return Modality.FINAL
if (this !is CallableMemberDescriptor) return Modality.FINAL
if (this.overriddenDescriptors.isNotEmpty()) {
if (containingClassDescriptor.modality != Modality.FINAL) return Modality.OPEN
}
if (containingClassDescriptor.kind == ClassKind.INTERFACE && this.visibility != Visibilities.PRIVATE) {
return if (this.modality == Modality.ABSTRACT) Modality.ABSTRACT else Modality.OPEN
}
return Modality.FINAL
}
private fun renderModalityForCallable(callable: CallableMemberDescriptor, builder: StringBuilder) {
if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.modality != Modality.FINAL) {
if (overrideRenderingPolicy == OverrideRenderingPolicy.RENDER_OVERRIDE && callable.modality == Modality.OPEN &&
overridesSomething(callable)) {
return
}
renderModality(callable.modality, builder)
renderModality(callable.modality, builder, callable.implicitModalityWithoutExtensions())
}
}
@@ -913,7 +929,7 @@ internal class DescriptorRendererImpl(
}
if (!(klass.kind == ClassKind.INTERFACE && klass.modality == Modality.ABSTRACT ||
klass.kind.isSingleton && klass.modality == Modality.FINAL)) {
renderModality(klass.modality, builder)
renderModality(klass.modality, builder, klass.implicitModalityWithoutExtensions())
}
renderMemberModifiers(klass, builder)
renderModifier(builder, DescriptorRendererModifier.INNER in modifiers && klass.isInner, "inner")
@@ -81,6 +81,7 @@ internal class DescriptorRendererOptionsImpl : DescriptorRendererOptions {
override var enhancedTypes by property(false)
override var normalizedVisibilities by property(false)
override var renderDefaultVisibility by property(true)
override var renderDefaultModality by property(true)
override var uninferredTypeParameterAsName by property(false)
override var includePropertyConstant by property(false)
override var withoutTypeParameters by property(false)
@@ -142,7 +142,7 @@ private fun OverrideMemberChooserObject.generateMember(
val bodyType = when {
targetClass?.hasExpectModifier() == true -> NO_BODY
descriptor.extensionReceiverParameter != null -> FROM_TEMPLATE
descriptor.extensionReceiverParameter != null && !forceActual -> FROM_TEMPLATE
else -> bodyType
}
@@ -211,27 +211,31 @@ private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
}
private val ACTUAL_RENDERER = OVERRIDE_RENDERER.withOptions {
modifiers = setOf(DescriptorRendererModifier.ANNOTATIONS)
modifiers = DescriptorRendererModifier.ALL
renderConstructorKeyword = true
secondaryConstructorsAsPrimary = false
renderDefaultVisibility = false
renderDefaultModality = false
}
private fun PropertyDescriptor.wrap(): PropertyDescriptor {
val delegate = copy(containingDeclaration, Modality.OPEN, visibility, kind, true) as PropertyDescriptor
private fun PropertyDescriptor.wrap(forceOverride: Boolean): PropertyDescriptor {
val delegate = copy(containingDeclaration, if (forceOverride) Modality.OPEN else modality, visibility, kind, true) as PropertyDescriptor
val newDescriptor = object : PropertyDescriptor by delegate {
override fun isExpect() = false
}
newDescriptor.setSingleOverridden(this)
if (forceOverride) {
newDescriptor.setSingleOverridden(this)
}
return newDescriptor
}
private fun FunctionDescriptor.wrap(): FunctionDescriptor {
private fun FunctionDescriptor.wrap(forceOverride: Boolean, forceAbstract: Boolean): FunctionDescriptor {
if (this is ClassConstructorDescriptor) return this.wrap()
return object : FunctionDescriptor by this {
override fun isExpect() = false
override fun getModality() = Modality.OPEN
override fun getModality() = if (forceAbstract) Modality.ABSTRACT else if (forceOverride) Modality.OPEN else this@wrap.modality
override fun getReturnType() = this@wrap.returnType?.approximateFlexibleTypes(preferNotNull = true, preferStarForRaw = true)
override fun getOverriddenDescriptors() = listOf(this@wrap)
override fun getOverriddenDescriptors() = if (forceOverride) listOf(this@wrap) else emptyList()
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D) =
visitor.visitFunctionDescriptor(this, data)
}
@@ -242,7 +246,7 @@ private fun ClassConstructorDescriptor.wrap(): ClassConstructorDescriptor {
override fun isExpect() = false
override fun getModality() = Modality.FINAL
override fun getReturnType() = this@wrap.returnType.approximateFlexibleTypes(preferNotNull = true, preferStarForRaw = true)
override fun getOverriddenDescriptors() = listOf(this@wrap)
override fun getOverriddenDescriptors(): List<ClassConstructorDescriptor> = emptyList()
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D) =
visitor.visitConstructorDescriptor(this, data)
}
@@ -254,7 +258,8 @@ private fun generateProperty(
renderer: DescriptorRenderer,
bodyType: OverrideMemberChooserObject.BodyType
): KtProperty {
val newDescriptor = descriptor.wrap()
val actualRendererUsed = renderer === ACTUAL_RENDERER
val newDescriptor = descriptor.wrap(forceOverride = !actualRendererUsed)
val returnType = descriptor.returnType
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
@@ -274,7 +279,8 @@ private fun generateProperty(
}
private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor, renderer: DescriptorRenderer): KtParameter {
val newDescriptor = descriptor.wrap()
val actualRendererUsed = renderer === ACTUAL_RENDERER
val newDescriptor = descriptor.wrap(forceOverride = !actualRendererUsed)
newDescriptor.setSingleOverridden(descriptor)
return KtPsiFactory(project).createParameter(renderer.render(newDescriptor))
}
@@ -285,7 +291,8 @@ private fun generateFunction(
renderer: DescriptorRenderer,
bodyType: OverrideMemberChooserObject.BodyType
): KtFunction {
val newDescriptor = descriptor.wrap()
val actualRendererUsed = renderer === ACTUAL_RENDERER
val newDescriptor = descriptor.wrap(forceAbstract = actualRendererUsed && bodyType == NO_BODY, forceOverride = !actualRendererUsed)
val returnType = descriptor.returnType
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
@@ -25,17 +25,16 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.JavaDirectoryService
import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
import org.jetbrains.kotlin.idea.core.*
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.NO_BODY
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.Companion.create
import org.jetbrains.kotlin.idea.core.overrideImplement.generateActualMember
import org.jetbrains.kotlin.idea.core.overrideImplement.generateTopLevelActual
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
@@ -252,7 +251,6 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
} else {
createClass(expectedText)
}
val isInterface = expectedClass is KtClass && expectedClass.isInterface()
actualClass.declarations.forEach {
if (it.exists()) {
it.delete()
@@ -261,16 +259,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
when (it) {
is KtEnumEntry -> return@forEach
is KtClassOrObject -> it.delete()
is KtCallableDeclaration -> {
if (!isInterface && !it.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
it.delete()
} else {
it.addModifier(KtTokens.ACTUAL_KEYWORD)
if (it is KtFunction) {
it.removeParameterDefaultValues()
}
}
}
is KtCallableDeclaration -> it.delete()
}
}
val primaryConstructor = actualClass.primaryConstructor
@@ -307,9 +296,6 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
continue@declLoop
}
is KtCallableDeclaration -> {
if (isInterface || expectedDeclaration.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
continue@declLoop
}
when (expectedDeclaration) {
is KtFunction -> generateFunction(project, expectedDeclaration, descriptor as FunctionDescriptor, actualClass)
is KtProperty -> generateProperty(project, expectedDeclaration, descriptor as PropertyDescriptor, actualClass)
@@ -346,8 +332,9 @@ private fun generateFunction(
descriptor: FunctionDescriptor,
targetClass: KtClassOrObject? = null
): KtFunction {
val memberChooserObject = OverrideMemberChooserObject.create(
expectedFunction, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE
val memberChooserObject = create(
expectedFunction, descriptor, descriptor,
if (descriptor.modality == Modality.ABSTRACT) NO_BODY else EMPTY_OR_TEMPLATE
)
return if (targetClass != null) {
memberChooserObject.generateActualMember(targetClass = targetClass, copyDoc = true)
@@ -372,14 +359,14 @@ private fun generateProperty(
descriptor: PropertyDescriptor,
targetClass: KtClassOrObject? = null
): KtProperty {
val memberChooserObject = OverrideMemberChooserObject.create(
expectedProperty, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE
val memberChooserObject = create(
expectedProperty, descriptor, descriptor,
if (descriptor.modality == Modality.ABSTRACT) NO_BODY else EMPTY_OR_TEMPLATE
)
return if (targetClass != null) {
memberChooserObject.generateActualMember(targetClass = targetClass, copyDoc = true)
} else {
memberChooserObject.generateTopLevelActual(copyDoc = true, project = project)
} as KtProperty
}
@@ -1,13 +1,12 @@
// Abstract: to be implemented
actual abstract class Abstract {
actual abstract fun String.bar(y: Double): Boolean
actual abstract var status: Int
actual fun foo(param: String): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
actual abstract fun String.bar(y: Double): Boolean
actual val isGood: Boolean
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
actual abstract var status: Int
}
@@ -0,0 +1,7 @@
// "Create actual class for module proj_JVM (JVM)" "true"
import kotlin.random.Random
expect abstract class My<caret>Generator {
abstract fun generate(): Random
}
@@ -0,0 +1,7 @@
// "Create actual class for module proj_JVM (JVM)" "true"
import kotlin.random.Random
expect abstract class MyGenerator {
abstract fun generate(): Random
}
@@ -0,0 +1 @@
// MyGenerator: to be implemented
@@ -0,0 +1,6 @@
import kotlin.random.Random
// MyGenerator: to be implemented
actual abstract class MyGenerator {
actual abstract fun generate(): Random
}
@@ -1,11 +1,8 @@
// Interface: to be implemented
actual interface Interface {
actual fun foo(param: String): Int
actual fun String.bar(y: Double): Boolean
actual val isGood: Boolean
actual var status: Int
actual class Nested {
@@ -30,6 +30,11 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul
runTest("idea/testData/multiModuleQuickFix/abstract/");
}
@TestMetadata("abstractClassWithJdk")
public void testAbstractClassWithJdk() throws Exception {
runTest("idea/testData/multiModuleQuickFix/abstractClassWithJdk/");
}
@TestMetadata("actualImplementAsConstructorParam")
public void testActualImplementAsConstructorParam() throws Exception {
runTest("idea/testData/multiModuleQuickFix/actualImplementAsConstructorParam/");