Introduce quick-fix "create expected class / function / property"
#KT-27075 Fixed
This commit is contained in:
@@ -188,7 +188,8 @@ interface DescriptorRendererOptions {
|
|||||||
var renderDefaultVisibility: Boolean
|
var renderDefaultVisibility: Boolean
|
||||||
var renderDefaultModality: Boolean
|
var renderDefaultModality: Boolean
|
||||||
var renderConstructorDelegation: Boolean
|
var renderConstructorDelegation: Boolean
|
||||||
var renderActualAnnotationPropertiesInPrimaryConstructor: Boolean
|
var renderAnnotationPropertiesInPrimaryConstructor: Boolean
|
||||||
|
var actualPropertiesInPrimaryConstructor: Boolean
|
||||||
var uninferredTypeParameterAsName: Boolean
|
var uninferredTypeParameterAsName: Boolean
|
||||||
var overrideRenderingPolicy: OverrideRenderingPolicy
|
var overrideRenderingPolicy: OverrideRenderingPolicy
|
||||||
var valueParametersHandler: DescriptorRenderer.ValueParametersHandler
|
var valueParametersHandler: DescriptorRenderer.ValueParametersHandler
|
||||||
|
|||||||
@@ -810,8 +810,8 @@ internal class DescriptorRendererImpl(
|
|||||||
renderModifier(builder, valueParameter.isNoinline, "noinline")
|
renderModifier(builder, valueParameter.isNoinline, "noinline")
|
||||||
|
|
||||||
val containingDeclaration = valueParameter.containingDeclaration
|
val containingDeclaration = valueParameter.containingDeclaration
|
||||||
if (renderActualAnnotationPropertiesInPrimaryConstructor && containingDeclaration.isAnnotationConstructor()) {
|
if (renderAnnotationPropertiesInPrimaryConstructor && containingDeclaration.isAnnotationConstructor()) {
|
||||||
renderModifier(builder, true, "actual")
|
renderModifier(builder, actualPropertiesInPrimaryConstructor, "actual")
|
||||||
renderModifier(builder, true, "val")
|
renderModifier(builder, true, "val")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ internal class DescriptorRendererOptionsImpl : DescriptorRendererOptions {
|
|||||||
override var renderDefaultVisibility by property(true)
|
override var renderDefaultVisibility by property(true)
|
||||||
override var renderDefaultModality by property(true)
|
override var renderDefaultModality by property(true)
|
||||||
override var renderConstructorDelegation by property(false)
|
override var renderConstructorDelegation by property(false)
|
||||||
override var renderActualAnnotationPropertiesInPrimaryConstructor by property(false)
|
override var renderAnnotationPropertiesInPrimaryConstructor by property(false)
|
||||||
|
override var actualPropertiesInPrimaryConstructor: Boolean by property(false)
|
||||||
override var uninferredTypeParameterAsName by property(false)
|
override var uninferredTypeParameterAsName by property(false)
|
||||||
override var includePropertyConstant by property(false)
|
override var includePropertyConstant by property(false)
|
||||||
override var withoutTypeParameters by property(false)
|
override var withoutTypeParameters by property(false)
|
||||||
|
|||||||
+57
-30
@@ -120,33 +120,48 @@ interface OverrideMemberChooserObject : ClassMember {
|
|||||||
fun OverrideMemberChooserObject.generateTopLevelActual(
|
fun OverrideMemberChooserObject.generateTopLevelActual(
|
||||||
copyDoc: Boolean,
|
copyDoc: Boolean,
|
||||||
project: Project
|
project: Project
|
||||||
) = generateMember(null, copyDoc, project, forceActual = true)
|
) = generateMember(null, copyDoc, project, forceActual = true, forceExpect = false)
|
||||||
|
|
||||||
fun OverrideMemberChooserObject.generateActualMember(
|
fun OverrideMemberChooserObject.generateActualMember(
|
||||||
targetClass: KtClassOrObject,
|
targetClass: KtClassOrObject,
|
||||||
copyDoc: Boolean
|
copyDoc: Boolean
|
||||||
) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = true)
|
) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = true, forceExpect = false)
|
||||||
|
|
||||||
|
fun OverrideMemberChooserObject.generateTopLevelExpect(
|
||||||
|
copyDoc: Boolean,
|
||||||
|
project: Project
|
||||||
|
) = generateMember(null, copyDoc, project, forceActual = false, forceExpect = true)
|
||||||
|
|
||||||
|
fun OverrideMemberChooserObject.generateExpectMember(
|
||||||
|
targetClass: KtClassOrObject,
|
||||||
|
copyDoc: Boolean
|
||||||
|
) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = false, forceExpect = true)
|
||||||
|
|
||||||
fun OverrideMemberChooserObject.generateMember(
|
fun OverrideMemberChooserObject.generateMember(
|
||||||
targetClass: KtClassOrObject,
|
targetClass: KtClassOrObject,
|
||||||
copyDoc: Boolean
|
copyDoc: Boolean
|
||||||
) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = false)
|
) = generateMember(targetClass, copyDoc, targetClass.project, forceActual = false, forceExpect = false)
|
||||||
|
|
||||||
private fun OverrideMemberChooserObject.generateMember(
|
private fun OverrideMemberChooserObject.generateMember(
|
||||||
targetClass: KtClassOrObject?,
|
targetClass: KtClassOrObject?,
|
||||||
copyDoc: Boolean,
|
copyDoc: Boolean,
|
||||||
project: Project,
|
project: Project,
|
||||||
forceActual: Boolean
|
forceActual: Boolean,
|
||||||
|
forceExpect: Boolean
|
||||||
): KtCallableDeclaration {
|
): KtCallableDeclaration {
|
||||||
val descriptor = immediateSuper
|
val descriptor = immediateSuper
|
||||||
|
|
||||||
val bodyType = when {
|
val bodyType = when {
|
||||||
targetClass?.hasExpectModifier() == true -> NO_BODY
|
targetClass?.hasExpectModifier() == true -> NO_BODY
|
||||||
descriptor.extensionReceiverParameter != null && !forceActual -> FROM_TEMPLATE
|
descriptor.extensionReceiverParameter != null && !forceActual && !forceExpect -> FROM_TEMPLATE
|
||||||
else -> bodyType
|
else -> bodyType
|
||||||
}
|
}
|
||||||
|
|
||||||
val renderer = if (forceActual) ACTUAL_RENDERER else OVERRIDE_RENDERER
|
val renderer = when {
|
||||||
|
forceActual -> ACTUAL_RENDERER
|
||||||
|
forceExpect -> EXPECT_RENDERER
|
||||||
|
else -> OVERRIDE_RENDERER
|
||||||
|
}
|
||||||
|
|
||||||
if (preferConstructorParameter && descriptor is PropertyDescriptor) {
|
if (preferConstructorParameter && descriptor is PropertyDescriptor) {
|
||||||
return generateConstructorParameter(project, descriptor, renderer)
|
return generateConstructorParameter(project, descriptor, renderer)
|
||||||
@@ -158,21 +173,27 @@ private fun OverrideMemberChooserObject.generateMember(
|
|||||||
else -> error("Unknown member to override: $descriptor")
|
else -> error("Unknown member to override: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forceActual) {
|
when {
|
||||||
newMember.addModifier(KtTokens.ACTUAL_KEYWORD)
|
forceActual -> newMember.addModifier(KtTokens.ACTUAL_KEYWORD)
|
||||||
} else if (targetClass?.hasActualModifier() == true) {
|
forceExpect -> if (targetClass == null) {
|
||||||
val expectClassDescriptors =
|
newMember.addModifier(KtTokens.EXPECT_KEYWORD)
|
||||||
targetClass.resolveToDescriptorIfAny()?.expectedDescriptors()?.filterIsInstance<ClassDescriptor>().orEmpty()
|
} else {
|
||||||
if (expectClassDescriptors.any { expectClassDescriptor ->
|
newMember.makeNotActual()
|
||||||
val expectMemberDescriptor = expectClassDescriptor.findCallableMemberBySignature(immediateSuper)
|
}
|
||||||
expectMemberDescriptor?.isExpect == true && expectMemberDescriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
targetClass?.hasActualModifier() == true -> {
|
||||||
}
|
val expectClassDescriptors =
|
||||||
) {
|
targetClass.resolveToDescriptorIfAny()?.expectedDescriptors()?.filterIsInstance<ClassDescriptor>().orEmpty()
|
||||||
newMember.addModifier(KtTokens.ACTUAL_KEYWORD)
|
if (expectClassDescriptors.any { expectClassDescriptor ->
|
||||||
|
val expectMemberDescriptor = expectClassDescriptor.findCallableMemberBySignature(immediateSuper)
|
||||||
|
expectMemberDescriptor?.isExpect == true && expectMemberDescriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
newMember.addModifier(KtTokens.ACTUAL_KEYWORD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
newMember.makeNotActual()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
newMember.removeModifier(KtTokens.IMPL_KEYWORD)
|
|
||||||
newMember.removeModifier(KtTokens.ACTUAL_KEYWORD)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copyDoc) {
|
if (copyDoc) {
|
||||||
@@ -210,14 +231,18 @@ private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
|
|||||||
presentableUnresolvedTypes = true
|
presentableUnresolvedTypes = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ACTUAL_RENDERER = OVERRIDE_RENDERER.withOptions {
|
private val EXPECT_RENDERER = OVERRIDE_RENDERER.withOptions {
|
||||||
modifiers = DescriptorRendererModifier.ALL
|
modifiers = DescriptorRendererModifier.ALL
|
||||||
renderConstructorKeyword = true
|
renderConstructorKeyword = true
|
||||||
secondaryConstructorsAsPrimary = false
|
secondaryConstructorsAsPrimary = false
|
||||||
renderDefaultVisibility = false
|
renderDefaultVisibility = false
|
||||||
renderDefaultModality = false
|
renderDefaultModality = false
|
||||||
renderConstructorDelegation = true
|
renderConstructorDelegation = true
|
||||||
renderActualAnnotationPropertiesInPrimaryConstructor = true
|
renderAnnotationPropertiesInPrimaryConstructor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ACTUAL_RENDERER = EXPECT_RENDERER.withOptions {
|
||||||
|
actualPropertiesInPrimaryConstructor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PropertyDescriptor.wrap(forceOverride: Boolean): PropertyDescriptor {
|
private fun PropertyDescriptor.wrap(forceOverride: Boolean): PropertyDescriptor {
|
||||||
@@ -237,7 +262,7 @@ private fun FunctionDescriptor.wrap(forceOverride: Boolean, forceAbstract: Boole
|
|||||||
override fun isExpect() = false
|
override fun isExpect() = false
|
||||||
override fun getModality() = if (forceAbstract) Modality.ABSTRACT else if (forceOverride) Modality.OPEN else this@wrap.modality
|
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 getReturnType() = this@wrap.returnType?.approximateFlexibleTypes(preferNotNull = true, preferStarForRaw = true)
|
||||||
override fun getOverriddenDescriptors() = if (forceOverride) listOf(this@wrap) else emptyList()
|
override fun getOverriddenDescriptors() = if (forceOverride) listOf(this@wrap) else this@wrap.overriddenDescriptors
|
||||||
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D) =
|
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D) =
|
||||||
visitor.visitFunctionDescriptor(this, data)
|
visitor.visitFunctionDescriptor(this, data)
|
||||||
}
|
}
|
||||||
@@ -260,8 +285,7 @@ private fun generateProperty(
|
|||||||
renderer: DescriptorRenderer,
|
renderer: DescriptorRenderer,
|
||||||
bodyType: OverrideMemberChooserObject.BodyType
|
bodyType: OverrideMemberChooserObject.BodyType
|
||||||
): KtProperty {
|
): KtProperty {
|
||||||
val actualRendererUsed = renderer === ACTUAL_RENDERER
|
val newDescriptor = descriptor.wrap(forceOverride = renderer === OVERRIDE_RENDERER)
|
||||||
val newDescriptor = descriptor.wrap(forceOverride = !actualRendererUsed)
|
|
||||||
|
|
||||||
val returnType = descriptor.returnType
|
val returnType = descriptor.returnType
|
||||||
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
||||||
@@ -281,8 +305,7 @@ private fun generateProperty(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor, renderer: DescriptorRenderer): KtParameter {
|
private fun generateConstructorParameter(project: Project, descriptor: PropertyDescriptor, renderer: DescriptorRenderer): KtParameter {
|
||||||
val actualRendererUsed = renderer === ACTUAL_RENDERER
|
val newDescriptor = descriptor.wrap(forceOverride = renderer === OVERRIDE_RENDERER)
|
||||||
val newDescriptor = descriptor.wrap(forceOverride = !actualRendererUsed)
|
|
||||||
newDescriptor.setSingleOverridden(descriptor)
|
newDescriptor.setSingleOverridden(descriptor)
|
||||||
return KtPsiFactory(project).createParameter(renderer.render(newDescriptor))
|
return KtPsiFactory(project).createParameter(renderer.render(newDescriptor))
|
||||||
}
|
}
|
||||||
@@ -293,8 +316,9 @@ private fun generateFunction(
|
|||||||
renderer: DescriptorRenderer,
|
renderer: DescriptorRenderer,
|
||||||
bodyType: OverrideMemberChooserObject.BodyType
|
bodyType: OverrideMemberChooserObject.BodyType
|
||||||
): KtFunction {
|
): KtFunction {
|
||||||
val actualRendererUsed = renderer === ACTUAL_RENDERER
|
val newDescriptor = descriptor.wrap(
|
||||||
val newDescriptor = descriptor.wrap(forceAbstract = actualRendererUsed && bodyType == NO_BODY, forceOverride = !actualRendererUsed)
|
forceAbstract = renderer === ACTUAL_RENDERER && bodyType == NO_BODY, forceOverride = renderer === OVERRIDE_RENDERER
|
||||||
|
)
|
||||||
|
|
||||||
val returnType = descriptor.returnType
|
val returnType = descriptor.returnType
|
||||||
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
||||||
@@ -363,4 +387,7 @@ fun generateUnsupportedOrSuperCall(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtNamedDeclaration.makeNotActual() {
|
||||||
|
removeModifier(KtTokens.ACTUAL_KEYWORD)
|
||||||
|
removeModifier(KtTokens.IMPL_KEYWORD)
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateP
|
|||||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByRefActionFactory
|
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByRefActionFactory
|
||||||
import org.jetbrains.kotlin.idea.quickfix.expectactual.AddActualFix
|
import org.jetbrains.kotlin.idea.quickfix.expectactual.AddActualFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.expectactual.CreateActualFix
|
import org.jetbrains.kotlin.idea.quickfix.expectactual.CreateActualFix
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.expectactual.CreateExpectedFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.migration.MigrateExternalExtensionFix
|
import org.jetbrains.kotlin.idea.quickfix.migration.MigrateExternalExtensionFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.migration.MigrateTypeParameterListFix
|
import org.jetbrains.kotlin.idea.quickfix.migration.MigrateTypeParameterListFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageFix
|
import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageFix
|
||||||
@@ -510,6 +511,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.registerFactory(RemoveAnnotationFix.JvmOverloads)
|
OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.registerFactory(RemoveAnnotationFix.JvmOverloads)
|
||||||
|
|
||||||
ACTUAL_WITHOUT_EXPECT.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ACTUAL_KEYWORD))
|
ACTUAL_WITHOUT_EXPECT.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ACTUAL_KEYWORD))
|
||||||
|
ACTUAL_WITHOUT_EXPECT.registerFactory(CreateExpectedFix)
|
||||||
NO_ACTUAL_FOR_EXPECT.registerFactory(CreateActualFix)
|
NO_ACTUAL_FOR_EXPECT.registerFactory(CreateActualFix)
|
||||||
NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.registerFactory(AddActualFix)
|
NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.registerFactory(AddActualFix)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.JavaDirectoryService
|
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -31,18 +30,17 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||||
import org.jetbrains.kotlin.idea.core.*
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE
|
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.BodyType.NO_BODY
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.Companion.create
|
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.generateActualMember
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateTopLevelActual
|
import org.jetbrains.kotlin.idea.core.overrideImplement.generateTopLevelActual
|
||||||
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||||
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
|
||||||
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -110,37 +108,7 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
|
|||||||
return actualDeclaration.containingKtFile
|
return actualDeclaration.containingKtFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val name = declaration.name ?: return null
|
return createFileForDeclaration(actualModule, declaration)
|
||||||
|
|
||||||
val expectedDir = declaration.containingFile.containingDirectory
|
|
||||||
val expectedPackage = JavaDirectoryService.getInstance().getPackage(expectedDir)
|
|
||||||
|
|
||||||
val actualDirectory = findOrCreateDirectoryForPackage(
|
|
||||||
actualModule, expectedPackage?.qualifiedName ?: ""
|
|
||||||
) ?: return null
|
|
||||||
return runWriteAction {
|
|
||||||
val fileName = "$name.kt"
|
|
||||||
val existingFile = actualDirectory.findFile(fileName)
|
|
||||||
val packageDirective = declaration.containingKtFile.packageDirective
|
|
||||||
val packageName =
|
|
||||||
if (packageDirective?.packageNameExpression == null) actualDirectory.getPackage()?.qualifiedName
|
|
||||||
else packageDirective.fqName.asString()
|
|
||||||
if (existingFile is KtFile) {
|
|
||||||
val existingPackageDirective = existingFile.packageDirective
|
|
||||||
if (existingFile.declarations.isNotEmpty() &&
|
|
||||||
existingPackageDirective?.fqName != packageDirective?.fqName
|
|
||||||
) {
|
|
||||||
val newName = KotlinNameSuggester.suggestNameByName(name) {
|
|
||||||
actualDirectory.findFile("$it.kt") == null
|
|
||||||
} + ".kt"
|
|
||||||
createKotlinFile(newName, actualDirectory, packageName)
|
|
||||||
} else {
|
|
||||||
existingFile
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
createKotlinFile(fileName, actualDirectory, packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : KotlinSingleIntentionActionFactory() {
|
companion object : KotlinSingleIntentionActionFactory() {
|
||||||
@@ -171,19 +139,7 @@ class CreateActualClassFix(
|
|||||||
generateClassOrObjectByExpectedClass(project, element, actualNeeded = true)
|
generateClassOrObjectByExpectedClass(project, element, actualNeeded = true)
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
override val elementType = run {
|
override val elementType = element.getTypeDescription()
|
||||||
val element = element
|
|
||||||
when (element) {
|
|
||||||
is KtObjectDeclaration -> "object"
|
|
||||||
is KtClass -> when {
|
|
||||||
element.isInterface() -> "interface"
|
|
||||||
element.isEnum() -> "enum class"
|
|
||||||
element.isAnnotation() -> "annotation class"
|
|
||||||
else -> "class"
|
|
||||||
}
|
|
||||||
else -> "class"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateActualPropertyFix(
|
class CreateActualPropertyFix(
|
||||||
@@ -242,16 +198,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val expectedText = expectedClass.text
|
val actualClass = createClassCopyByText(expectedClass)
|
||||||
val actualClass = if (expectedClass is KtObjectDeclaration) {
|
|
||||||
if (expectedClass.isCompanion()) {
|
|
||||||
createCompanionObject(expectedText)
|
|
||||||
} else {
|
|
||||||
createObject(expectedText)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
createClass(expectedText)
|
|
||||||
}
|
|
||||||
actualClass.declarations.forEach {
|
actualClass.declarations.forEach {
|
||||||
if (it.exists()) {
|
if (it.exists()) {
|
||||||
it.delete()
|
it.delete()
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.quickfix.expectactual
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
|
import com.intellij.ide.util.EditorHelper
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.project.DumbService
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
|
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.implementedModules
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||||
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.idea.core.overrideImplement.*
|
||||||
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
|
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||||
|
import org.jetbrains.kotlin.idea.util.module
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
sealed class CreateExpectedFix<out D : KtNamedDeclaration>(
|
||||||
|
declaration: D,
|
||||||
|
targetExpectedClass: KtClassOrObject?,
|
||||||
|
private val commonModule: Module,
|
||||||
|
private val generateIt: KtPsiFactory.(Project, D) -> D?
|
||||||
|
) : KotlinQuickFixAction<D>(declaration) {
|
||||||
|
|
||||||
|
private val targetExpectedClassPointer = targetExpectedClass?.createSmartPointer()
|
||||||
|
|
||||||
|
override fun getFamilyName() = text
|
||||||
|
|
||||||
|
protected abstract val elementType: String
|
||||||
|
|
||||||
|
override fun getText() = "Create expected $elementType in common module ${commonModule.name}"
|
||||||
|
|
||||||
|
override fun startInWriteAction() = false
|
||||||
|
|
||||||
|
final override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
|
val element = element ?: return
|
||||||
|
val factory = KtPsiFactory(project)
|
||||||
|
|
||||||
|
val targetExpectedClass = targetExpectedClassPointer?.element
|
||||||
|
val expectedFile = targetExpectedClass?.containingKtFile ?: getOrCreateImplementationFile() ?: return
|
||||||
|
DumbService.getInstance(project).runWhenSmart {
|
||||||
|
val generated = factory.generateIt(project, element) ?: return@runWhenSmart
|
||||||
|
|
||||||
|
project.executeWriteCommand("Create expected declaration") {
|
||||||
|
if (expectedFile.packageDirective?.fqName != file.packageDirective?.fqName &&
|
||||||
|
expectedFile.declarations.isEmpty()
|
||||||
|
) {
|
||||||
|
val packageDirective = file.packageDirective
|
||||||
|
packageDirective?.let {
|
||||||
|
val oldPackageDirective = expectedFile.packageDirective
|
||||||
|
val newPackageDirective = factory.createPackageDirective(it.fqName)
|
||||||
|
if (oldPackageDirective != null) {
|
||||||
|
oldPackageDirective.replace(newPackageDirective)
|
||||||
|
} else {
|
||||||
|
expectedFile.add(newPackageDirective)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val expectedDeclaration = when {
|
||||||
|
targetExpectedClass != null -> targetExpectedClass.addDeclaration(generated as KtNamedDeclaration)
|
||||||
|
else -> expectedFile.add(generated) as KtElement
|
||||||
|
}
|
||||||
|
val reformatted = CodeStyleManager.getInstance(project).reformat(expectedDeclaration)
|
||||||
|
val shortened = ShortenReferences.DEFAULT.process(reformatted as KtElement)
|
||||||
|
EditorHelper.openInEditor(shortened)?.caretModel?.moveToOffset(shortened.textRange.startOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOrCreateImplementationFile(): KtFile? {
|
||||||
|
val declaration = element as? KtNamedDeclaration ?: return null
|
||||||
|
val parent = declaration.parent
|
||||||
|
if (parent is KtFile) {
|
||||||
|
for (otherDeclaration in parent.declarations) {
|
||||||
|
if (otherDeclaration === declaration) continue
|
||||||
|
if (!otherDeclaration.hasActualModifier()) continue
|
||||||
|
val expectedDeclaration = otherDeclaration.liftToExpected() ?: continue
|
||||||
|
return expectedDeclaration.containingKtFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createFileForDeclaration(commonModule, declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : KotlinIntentionActionsFactory() {
|
||||||
|
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
||||||
|
val d = DiagnosticFactory.cast(diagnostic, Errors.ACTUAL_WITHOUT_EXPECT)
|
||||||
|
val declaration = d.psiElement as? KtNamedDeclaration ?: return emptyList()
|
||||||
|
val compatibility = d.b
|
||||||
|
// For function we allow it, because overloads are possible
|
||||||
|
if (compatibility.isNotEmpty() && declaration !is KtFunction) return emptyList()
|
||||||
|
|
||||||
|
val containingClass = declaration.containingClassOrObject
|
||||||
|
val expectedContainingClass = containingClass?.liftToExpected() as? KtClassOrObject
|
||||||
|
// If there is already an expected class, we suggest only for its module,
|
||||||
|
// otherwise we suggest for all relevant expected modules
|
||||||
|
val expectedModules = expectedContainingClass?.module?.let { listOf(it) }
|
||||||
|
?: declaration.module?.implementedModules
|
||||||
|
?: return emptyList()
|
||||||
|
return when (declaration) {
|
||||||
|
is KtClassOrObject -> expectedModules.map { CreateExpectedClassFix(declaration, expectedContainingClass, it) }
|
||||||
|
is KtFunction -> expectedModules.map { CreateExpectedFunctionFix(declaration, expectedContainingClass, it) }
|
||||||
|
is KtProperty, is KtParameter -> expectedModules.map { CreateExpectedPropertyFix(declaration, expectedContainingClass, it) }
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateExpectedClassFix(
|
||||||
|
klass: KtClassOrObject,
|
||||||
|
outerExpectedClass: KtClassOrObject?,
|
||||||
|
commonModule: Module
|
||||||
|
) : CreateExpectedFix<KtClassOrObject>(klass, outerExpectedClass, commonModule, { project, element ->
|
||||||
|
generateClassOrObjectByActualClass(project, element, isNested = outerExpectedClass != null)
|
||||||
|
}) {
|
||||||
|
|
||||||
|
override val elementType = element.getTypeDescription()
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateExpectedPropertyFix(
|
||||||
|
property: KtNamedDeclaration,
|
||||||
|
targetExpectedClass: KtClassOrObject?,
|
||||||
|
commonModule: Module
|
||||||
|
) : CreateExpectedFix<KtNamedDeclaration>(property, targetExpectedClass, commonModule, { project, element ->
|
||||||
|
val descriptor = element.toDescriptor() as? PropertyDescriptor
|
||||||
|
descriptor?.let { generateProperty(project, element, descriptor, targetExpectedClass) }
|
||||||
|
}) {
|
||||||
|
|
||||||
|
override val elementType = "property"
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateExpectedFunctionFix(
|
||||||
|
function: KtFunction,
|
||||||
|
targetExpectedClass: KtClassOrObject?,
|
||||||
|
commonModule: Module
|
||||||
|
) : CreateExpectedFix<KtFunction>(function, targetExpectedClass, commonModule, { project, element ->
|
||||||
|
val descriptor = element.toDescriptor() as? FunctionDescriptor
|
||||||
|
descriptor?.let { generateFunction(project, element, descriptor, targetExpectedClass) }
|
||||||
|
}) {
|
||||||
|
|
||||||
|
override val elementType = "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtPsiFactory.generateClassOrObjectByActualClass(
|
||||||
|
project: Project,
|
||||||
|
actualClass: KtClassOrObject,
|
||||||
|
isNested: Boolean
|
||||||
|
): KtClassOrObject {
|
||||||
|
val expectedClass = createClassCopyByText(actualClass)
|
||||||
|
expectedClass.declarations.forEach {
|
||||||
|
when (it) {
|
||||||
|
is KtEnumEntry -> return@forEach
|
||||||
|
is KtClassOrObject -> it.delete()
|
||||||
|
is KtCallableDeclaration -> it.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectedClass.primaryConstructor?.delete()
|
||||||
|
|
||||||
|
val context = actualClass.analyzeWithContent()
|
||||||
|
expectedClass.superTypeListEntries.zip(actualClass.superTypeListEntries).forEach { (expectedEntry, actualEntry) ->
|
||||||
|
if (expectedEntry !is KtSuperTypeCallEntry) return@forEach
|
||||||
|
val superType = context[BindingContext.TYPE, actualEntry.typeReference]
|
||||||
|
val superClassDescriptor = superType?.constructor?.declarationDescriptor as? ClassDescriptor ?: return@forEach
|
||||||
|
if (superClassDescriptor.kind == ClassKind.CLASS || superClassDescriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
|
expectedEntry.replace(createSuperTypeEntry(expectedEntry.typeReference!!.text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isNested) {
|
||||||
|
expectedClass.addModifier(KtTokens.EXPECT_KEYWORD)
|
||||||
|
} else {
|
||||||
|
expectedClass.makeNotActual()
|
||||||
|
}
|
||||||
|
|
||||||
|
declLoop@ for (actualDeclaration in actualClass.declarations) {
|
||||||
|
val descriptor = actualDeclaration.toDescriptor() ?: continue
|
||||||
|
val expectedDeclaration: KtDeclaration = when (actualDeclaration) {
|
||||||
|
is KtClassOrObject ->
|
||||||
|
if (actualDeclaration !is KtEnumEntry) {
|
||||||
|
generateClassOrObjectByActualClass(project, actualDeclaration, isNested = true)
|
||||||
|
} else {
|
||||||
|
continue@declLoop
|
||||||
|
}
|
||||||
|
is KtCallableDeclaration -> {
|
||||||
|
when (actualDeclaration) {
|
||||||
|
is KtFunction -> generateFunction(project, actualDeclaration, descriptor as FunctionDescriptor, expectedClass)
|
||||||
|
is KtProperty -> generateProperty(project, actualDeclaration, descriptor as PropertyDescriptor, expectedClass)
|
||||||
|
else -> continue@declLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> continue@declLoop
|
||||||
|
}
|
||||||
|
expectedClass.addDeclaration(expectedDeclaration)
|
||||||
|
}
|
||||||
|
val actualPrimaryConstructor = actualClass.primaryConstructor
|
||||||
|
if (expectedClass is KtClass && actualPrimaryConstructor != null) {
|
||||||
|
val descriptor = actualPrimaryConstructor.toDescriptor()
|
||||||
|
if (descriptor is FunctionDescriptor) {
|
||||||
|
val expectedPrimaryConstructor = generateFunction(project, actualPrimaryConstructor, descriptor, expectedClass)
|
||||||
|
expectedClass.createPrimaryConstructorIfAbsent().replace(expectedPrimaryConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return expectedClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateFunction(
|
||||||
|
project: Project,
|
||||||
|
actualFunction: KtFunction,
|
||||||
|
descriptor: FunctionDescriptor,
|
||||||
|
targetClass: KtClassOrObject? = null
|
||||||
|
): KtFunction {
|
||||||
|
val memberChooserObject = OverrideMemberChooserObject.create(
|
||||||
|
actualFunction, descriptor, descriptor,
|
||||||
|
OverrideMemberChooserObject.BodyType.NO_BODY
|
||||||
|
)
|
||||||
|
return if (targetClass != null) {
|
||||||
|
memberChooserObject.generateExpectMember(targetClass = targetClass, copyDoc = true)
|
||||||
|
} else {
|
||||||
|
memberChooserObject.generateTopLevelExpect(copyDoc = true, project = project)
|
||||||
|
} as KtFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateProperty(
|
||||||
|
project: Project,
|
||||||
|
actualProperty: KtNamedDeclaration,
|
||||||
|
descriptor: PropertyDescriptor,
|
||||||
|
targetClass: KtClassOrObject? = null
|
||||||
|
): KtProperty {
|
||||||
|
val memberChooserObject = OverrideMemberChooserObject.create(
|
||||||
|
actualProperty, descriptor, descriptor,
|
||||||
|
OverrideMemberChooserObject.BodyType.NO_BODY
|
||||||
|
)
|
||||||
|
return if (targetClass != null) {
|
||||||
|
memberChooserObject.generateExpectMember(targetClass = targetClass, copyDoc = true)
|
||||||
|
} else {
|
||||||
|
memberChooserObject.generateTopLevelExpect(copyDoc = true, project = project)
|
||||||
|
} as KtProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.quickfix.expectactual
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.psi.JavaDirectoryService
|
||||||
|
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||||
|
import org.jetbrains.kotlin.idea.core.findOrCreateDirectoryForPackage
|
||||||
|
import org.jetbrains.kotlin.idea.core.getPackage
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
|
fun createFileForDeclaration(module: Module, declaration: KtNamedDeclaration): KtFile? {
|
||||||
|
val fileName = declaration.name ?: return null
|
||||||
|
|
||||||
|
val originalDir = declaration.containingFile.containingDirectory
|
||||||
|
val containerPackage = JavaDirectoryService.getInstance().getPackage(originalDir)
|
||||||
|
val packageDirective = declaration.containingKtFile.packageDirective
|
||||||
|
val directory = findOrCreateDirectoryForPackage(
|
||||||
|
module, containerPackage?.qualifiedName ?: ""
|
||||||
|
) ?: return null
|
||||||
|
return runWriteAction {
|
||||||
|
val fileNameWithExtension = "$fileName.kt"
|
||||||
|
val existingFile = directory.findFile(fileNameWithExtension)
|
||||||
|
val packageName =
|
||||||
|
if (packageDirective?.packageNameExpression == null) directory.getPackage()?.qualifiedName
|
||||||
|
else packageDirective.fqName.asString()
|
||||||
|
if (existingFile is KtFile) {
|
||||||
|
val existingPackageDirective = existingFile.packageDirective
|
||||||
|
if (existingFile.declarations.isNotEmpty() &&
|
||||||
|
existingPackageDirective?.fqName != packageDirective?.fqName
|
||||||
|
) {
|
||||||
|
val newName = KotlinNameSuggester.suggestNameByName(fileName) {
|
||||||
|
directory.findFile("$it.kt") == null
|
||||||
|
} + ".kt"
|
||||||
|
createKotlinFile(newName, directory, packageName)
|
||||||
|
} else {
|
||||||
|
existingFile
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createKotlinFile(fileNameWithExtension, directory, packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtPsiFactory.createClassCopyByText(originalClass: KtClassOrObject): KtClassOrObject {
|
||||||
|
val text = originalClass.text
|
||||||
|
return if (originalClass is KtObjectDeclaration) {
|
||||||
|
if (originalClass.isCompanion()) {
|
||||||
|
createCompanionObject(text)
|
||||||
|
} else {
|
||||||
|
createObject(text)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createClass(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtClassOrObject?.getTypeDescription(): String = when (this) {
|
||||||
|
is KtObjectDeclaration -> "object"
|
||||||
|
is KtClass -> when {
|
||||||
|
isInterface() -> "interface"
|
||||||
|
isEnum() -> "enum class"
|
||||||
|
isAnnotation() -> "annotation class"
|
||||||
|
else -> "class"
|
||||||
|
}
|
||||||
|
else -> "class"
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
expect annotation class My(val x: Int, val y: Double)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected annotation class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual annotation class <caret>My(actual val x: Int, actual val y: Double)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected annotation class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual annotation class My(actual val x: Int, actual val y: Double)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
expect class My {
|
||||||
|
fun foo(param: String): Int
|
||||||
|
fun String.bar(y: Double): Boolean
|
||||||
|
fun baz()
|
||||||
|
|
||||||
|
constructor(flag: Boolean)
|
||||||
|
|
||||||
|
val isGood: Boolean
|
||||||
|
var status: Int
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class <caret>My {
|
||||||
|
actual fun foo(param: String): Int = 42
|
||||||
|
|
||||||
|
actual fun String.bar(y: Double): Boolean = true
|
||||||
|
|
||||||
|
actual fun baz() {}
|
||||||
|
|
||||||
|
actual constructor(flag: Boolean) {}
|
||||||
|
|
||||||
|
actual val isGood: Boolean
|
||||||
|
get() = true
|
||||||
|
actual var status: Int
|
||||||
|
get() = 0
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual fun foo(param: String): Int = 42
|
||||||
|
|
||||||
|
actual fun String.bar(y: Double): Boolean = true
|
||||||
|
|
||||||
|
actual fun baz() {}
|
||||||
|
|
||||||
|
actual constructor(flag: Boolean) {}
|
||||||
|
|
||||||
|
actual val isGood: Boolean
|
||||||
|
get() = true
|
||||||
|
actual var status: Int
|
||||||
|
get() = 0
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My {
|
||||||
|
fun foo(param: String): Int
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected function in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual fun <caret>foo(param: String) = param.length
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected function in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual fun <caret>foo(param: String) = param.length
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My {
|
||||||
|
var s: String
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual var <caret>s: String = "Hello"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual var <caret>s: String = "Hello"
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My {
|
||||||
|
val s: String
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My(actual val <caret>s: String)
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My(actual val <caret>s: String)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect abstract class Base {
|
||||||
|
abstract fun foo(param: String): Int
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect abstract class Base {
|
||||||
|
abstract fun foo(param: String): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
expect class My : Base {
|
||||||
|
override fun foo(param: String): Int
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual abstract class Base {
|
||||||
|
actual abstract fun foo(param: String): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
actual class <caret>My : Base() {
|
||||||
|
actual override fun foo(param: String) = param.length
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual abstract class Base {
|
||||||
|
actual abstract fun foo(param: String): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
actual class My : Base() {
|
||||||
|
actual override fun foo(param: String) = param.length
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// My: to be implemented
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
expect enum class My {
|
||||||
|
FIRST,
|
||||||
|
SECOND,
|
||||||
|
LAST;
|
||||||
|
|
||||||
|
val num: Int
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create expected enum class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual enum class <caret>My {
|
||||||
|
FIRST,
|
||||||
|
SECOND,
|
||||||
|
LAST;
|
||||||
|
|
||||||
|
val num: Int get() = 42
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Create expected enum class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual enum class My {
|
||||||
|
FIRST,
|
||||||
|
SECOND,
|
||||||
|
LAST;
|
||||||
|
|
||||||
|
val num: Int get() = 42
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
expect fun foo(i: Int, d: Double, s: String): Boolean
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected function in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual fun <caret>foo(i: Int, d: Double, s: String) = s == "$i$d"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// "Create expected function in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual fun foo(i: Int, d: Double, s: String) = s == "$i$d"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
expect class My {
|
||||||
|
inner class Nested(s: String) {
|
||||||
|
fun hello(): String
|
||||||
|
var ss: String
|
||||||
|
|
||||||
|
class OtherNested(d: Double) {
|
||||||
|
val dd: Double
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual inner class <caret>Nested(actual val s: String) {
|
||||||
|
actual fun hello() = s
|
||||||
|
|
||||||
|
actual var ss = s
|
||||||
|
|
||||||
|
actual class OtherNested(actual var d: Double) {
|
||||||
|
actual val dd = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// "Create expected class in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual class My {
|
||||||
|
actual inner class <caret>Nested(actual val s: String) {
|
||||||
|
actual fun hello() = s
|
||||||
|
|
||||||
|
actual var ss = s
|
||||||
|
|
||||||
|
actual class OtherNested(actual var d: Double) {
|
||||||
|
actual val dd = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
expect var foo: String
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual var <caret>foo: String
|
||||||
|
get() = field * field
|
||||||
|
set(value) { field = value }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Create expected property in common module testModule_Common" "true"
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
|
||||||
|
actual var foo: String
|
||||||
|
get() = field * field
|
||||||
|
set(value) { field = value }
|
||||||
+50
@@ -254,6 +254,56 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul
|
|||||||
runTest("idea/testData/multiModuleQuickFix/enum/");
|
runTest("idea/testData/multiModuleQuickFix/enum/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectAnnotation")
|
||||||
|
public void testExpectAnnotation() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectAnnotation/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectClass")
|
||||||
|
public void testExpectClass() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectClass/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectClassFunction")
|
||||||
|
public void testExpectClassFunction() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectClassFunction/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectClassProperty")
|
||||||
|
public void testExpectClassProperty() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectClassProperty/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectClassPropertyInConstructor")
|
||||||
|
public void testExpectClassPropertyInConstructor() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectClassPropertyInConstructor/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectClassWithSupertype")
|
||||||
|
public void testExpectClassWithSupertype() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectClassWithSupertype/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectEnum")
|
||||||
|
public void testExpectEnum() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectEnum/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectFunction")
|
||||||
|
public void testExpectFunction() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectFunction/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectNestedClass")
|
||||||
|
public void testExpectNestedClass() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectNestedClass/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectProperty")
|
||||||
|
public void testExpectProperty() throws Exception {
|
||||||
|
runTest("idea/testData/multiModuleQuickFix/expectProperty/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("function")
|
@TestMetadata("function")
|
||||||
public void testFunction() throws Exception {
|
public void testFunction() throws Exception {
|
||||||
runTest("idea/testData/multiModuleQuickFix/function/");
|
runTest("idea/testData/multiModuleQuickFix/function/");
|
||||||
|
|||||||
Reference in New Issue
Block a user