Create actual fix: reformat

This commit is contained in:
Mikhail Glukhikh
2018-03-02 15:05:16 +03:00
parent 27d7bb595f
commit 3ec2dac10b
@@ -44,9 +44,9 @@ import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
sealed class CreateActualFix<out D : KtNamedDeclaration>( sealed class CreateActualFix<out D : KtNamedDeclaration>(
declaration: D, declaration: D,
private val actualPlatform: MultiTargetPlatform.Specific, private val actualPlatform: MultiTargetPlatform.Specific,
private val generateIt: KtPsiFactory.(Project, D) -> D? private val generateIt: KtPsiFactory.(Project, D) -> D?
) : KotlinQuickFixAction<D>(declaration) { ) : KotlinQuickFixAction<D>(declaration) {
override fun getFamilyName() = text override fun getFamilyName() = text
@@ -57,7 +57,7 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
override fun startInWriteAction() = false override fun startInWriteAction() = false
override final fun invoke(project: Project, editor: Editor?, file: KtFile) { final override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return val element = element ?: return
val factory = KtPsiFactory(project) val factory = KtPsiFactory(project)
@@ -66,15 +66,15 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
runWriteAction { runWriteAction {
if (actualFile.packageDirective?.fqName != file.packageDirective?.fqName && if (actualFile.packageDirective?.fqName != file.packageDirective?.fqName &&
actualFile.declarations.isEmpty()) { actualFile.declarations.isEmpty()
) {
val packageDirective = file.packageDirective val packageDirective = file.packageDirective
packageDirective?.let { packageDirective?.let {
val oldPackageDirective = actualFile.packageDirective val oldPackageDirective = actualFile.packageDirective
val newPackageDirective = factory.createPackageDirective(it.fqName) val newPackageDirective = factory.createPackageDirective(it.fqName)
if (oldPackageDirective != null) { if (oldPackageDirective != null) {
oldPackageDirective.replace(newPackageDirective) oldPackageDirective.replace(newPackageDirective)
} } else {
else {
actualFile.add(newPackageDirective) actualFile.add(newPackageDirective)
} }
} }
@@ -87,10 +87,10 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
} }
private fun implementationModuleOf(expectedModule: Module) = private fun implementationModuleOf(expectedModule: Module) =
expectedModule.implementingModules.firstOrNull { expectedModule.implementingModules.firstOrNull {
PackageUtil.checkSourceRootsConfigured(it, false) && PackageUtil.checkSourceRootsConfigured(it, false) &&
TargetPlatformDetector.getPlatform(it).multiTargetPlatform == actualPlatform TargetPlatformDetector.getPlatform(it).multiTargetPlatform == actualPlatform
} }
private fun getOrCreateImplementationFile(): KtFile? { private fun getOrCreateImplementationFile(): KtFile? {
val declaration = element as? KtNamedDeclaration ?: return null val declaration = element as? KtNamedDeclaration ?: return null
@@ -102,29 +102,28 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
val expectedModule = ModuleUtilCore.findModuleForPsiElement(declaration) ?: return null val expectedModule = ModuleUtilCore.findModuleForPsiElement(declaration) ?: return null
val actualModule = implementationModuleOf(expectedModule) ?: return null val actualModule = implementationModuleOf(expectedModule) ?: return null
val actualDirectory = PackageUtil.findOrCreateDirectoryForPackage( val actualDirectory = PackageUtil.findOrCreateDirectoryForPackage(
actualModule, expectedPackage?.qualifiedName ?: "", null, false actualModule, expectedPackage?.qualifiedName ?: "", null, false
) ?: return null ) ?: return null
return runWriteAction { return runWriteAction {
val fileName = "$name.kt" val fileName = "$name.kt"
val existingFile = actualDirectory.findFile(fileName) val existingFile = actualDirectory.findFile(fileName)
val packageDirective = declaration.containingKtFile.packageDirective val packageDirective = declaration.containingKtFile.packageDirective
val packageName = val packageName =
if (packageDirective?.packageNameExpression == null) actualDirectory.getPackage()?.qualifiedName if (packageDirective?.packageNameExpression == null) actualDirectory.getPackage()?.qualifiedName
else packageDirective.fqName.asString() else packageDirective.fqName.asString()
if (existingFile is KtFile) { if (existingFile is KtFile) {
val existingPackageDirective = existingFile.packageDirective val existingPackageDirective = existingFile.packageDirective
if (existingFile.declarations.isNotEmpty() && if (existingFile.declarations.isNotEmpty() &&
existingPackageDirective?.fqName != packageDirective?.fqName) { existingPackageDirective?.fqName != packageDirective?.fqName
) {
val newName = KotlinNameSuggester.suggestNameByName(name) { val newName = KotlinNameSuggester.suggestNameByName(name) {
actualDirectory.findFile("$it.kt") == null actualDirectory.findFile("$it.kt") == null
} + ".kt" } + ".kt"
createKotlinFile(newName, actualDirectory, packageName) createKotlinFile(newName, actualDirectory, packageName)
} } else {
else {
existingFile existingFile
} }
} } else {
else {
createKotlinFile(fileName, actualDirectory, packageName) createKotlinFile(fileName, actualDirectory, packageName)
} }
} }
@@ -149,8 +148,8 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
} }
class CreateActualClassFix( class CreateActualClassFix(
klass: KtClassOrObject, klass: KtClassOrObject,
actualPlatform: MultiTargetPlatform.Specific actualPlatform: MultiTargetPlatform.Specific
) : CreateActualFix<KtClassOrObject>(klass, actualPlatform, { project, element -> ) : CreateActualFix<KtClassOrObject>(klass, actualPlatform, { project, element ->
generateClassOrObjectByExpectedClass(project, element, actualNeeded = true) generateClassOrObjectByExpectedClass(project, element, actualNeeded = true)
}) { }) {
@@ -171,8 +170,8 @@ class CreateActualClassFix(
} }
class CreateActualPropertyFix( class CreateActualPropertyFix(
property: KtProperty, property: KtProperty,
actualPlatform: MultiTargetPlatform.Specific actualPlatform: MultiTargetPlatform.Specific
) : CreateActualFix<KtProperty>(property, actualPlatform, { project, element -> ) : CreateActualFix<KtProperty>(property, actualPlatform, { project, element ->
val descriptor = element.toDescriptor() as? PropertyDescriptor val descriptor = element.toDescriptor() as? PropertyDescriptor
descriptor?.let { generateProperty(project, element, descriptor, actualNeeded = true) } descriptor?.let { generateProperty(project, element, descriptor, actualNeeded = true) }
@@ -182,8 +181,8 @@ class CreateActualPropertyFix(
} }
class CreateActualFunctionFix( class CreateActualFunctionFix(
function: KtFunction, function: KtFunction,
actualPlatform: MultiTargetPlatform.Specific actualPlatform: MultiTargetPlatform.Specific
) : CreateActualFix<KtFunction>(function, actualPlatform, { project, element -> ) : CreateActualFix<KtFunction>(function, actualPlatform, { project, element ->
val descriptor = element.toDescriptor() as? FunctionDescriptor val descriptor = element.toDescriptor() as? FunctionDescriptor
descriptor?.let { generateFunction(project, element, descriptor, actualNeeded = true) } descriptor?.let { generateFunction(project, element, descriptor, actualNeeded = true) }
@@ -195,18 +194,17 @@ class CreateActualFunctionFix(
private fun KtModifierListOwner.replaceExpectModifier(actualNeeded: Boolean) { private fun KtModifierListOwner.replaceExpectModifier(actualNeeded: Boolean) {
if (actualNeeded) { if (actualNeeded) {
addModifier(KtTokens.ACTUAL_KEYWORD) addModifier(KtTokens.ACTUAL_KEYWORD)
} } else {
else {
removeModifier(KtTokens.HEADER_KEYWORD) removeModifier(KtTokens.HEADER_KEYWORD)
removeModifier(KtTokens.EXPECT_KEYWORD) removeModifier(KtTokens.EXPECT_KEYWORD)
} }
} }
internal fun KtPsiFactory.generateClassOrObjectByExpectedClass( internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
project: Project, project: Project,
expectedClass: KtClassOrObject, expectedClass: KtClassOrObject,
actualNeeded: Boolean, actualNeeded: Boolean,
existingDeclarations: List<KtDeclaration> = emptyList() existingDeclarations: List<KtDeclaration> = emptyList()
): KtClassOrObject { ): KtClassOrObject {
fun KtDeclaration.exists() = fun KtDeclaration.exists() =
existingDeclarations.any { existingDeclarations.any {
@@ -215,10 +213,10 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
is KtFunction -> { is KtFunction -> {
it as KtFunction it as KtFunction
valueParameters.size == it.valueParameters.size && valueParameters.size == it.valueParameters.size &&
valueParameters.zip(it.valueParameters).all { (parameter, existingParameter) -> valueParameters.zip(it.valueParameters).all { (parameter, existingParameter) ->
parameter.name == existingParameter.name && parameter.name == existingParameter.name &&
parameter.typeReference?.text == existingParameter.typeReference?.text parameter.typeReference?.text == existingParameter.typeReference?.text
} }
} }
else -> true else -> true
} }
@@ -246,8 +244,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
is KtCallableDeclaration -> { is KtCallableDeclaration -> {
if (!isInterface && !it.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { if (!isInterface && !it.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
it.delete() it.delete()
} } else {
else {
it.addModifier(KtTokens.ACTUAL_KEYWORD) it.addModifier(KtTokens.ACTUAL_KEYWORD)
} }
} }
@@ -260,8 +257,7 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
is KtClassOrObject -> is KtClassOrObject ->
if (expectedDeclaration !is KtEnumEntry) { if (expectedDeclaration !is KtEnumEntry) {
generateClassOrObjectByExpectedClass(project, expectedDeclaration, actualNeeded = true) generateClassOrObjectByExpectedClass(project, expectedDeclaration, actualNeeded = true)
} } else {
else {
continue@declLoop continue@declLoop
} }
is KtCallableDeclaration -> { is KtCallableDeclaration -> {
@@ -294,32 +290,30 @@ internal fun KtPsiFactory.generateClassOrObjectByExpectedClass(
} }
private fun KtPsiFactory.generateFunction( private fun KtPsiFactory.generateFunction(
project: Project, project: Project,
expectedFunction: KtFunction, expectedFunction: KtFunction,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
actualNeeded: Boolean actualNeeded: Boolean
): KtFunction { ): KtFunction {
val returnType = descriptor.returnType val returnType = descriptor.returnType
val body = run { val body = run {
if (returnType != null && !KotlinBuiltIns.isUnit(returnType)) { if (returnType != null && !KotlinBuiltIns.isUnit(returnType)) {
val delegation = getFunctionBodyTextFromTemplate( val delegation = getFunctionBodyTextFromTemplate(
project, project,
TemplateKind.FUNCTION, TemplateKind.FUNCTION,
descriptor.name.asString(), descriptor.name.asString(),
IdeDescriptorRenderers.SOURCE_CODE.renderType(returnType) IdeDescriptorRenderers.SOURCE_CODE.renderType(returnType)
) )
"{$delegation\n}" "{$delegation\n}"
} } else {
else {
"{}" "{}"
} }
} }
return (if (expectedFunction is KtSecondaryConstructor) { return (if (expectedFunction is KtSecondaryConstructor) {
createSecondaryConstructor(expectedFunction.text + " " + body) createSecondaryConstructor(expectedFunction.text + " " + body)
} } else {
else {
createFunction(expectedFunction.text + " " + body) createFunction(expectedFunction.text + " " + body)
} as KtFunction).apply { } as KtFunction).apply {
replaceExpectModifier(actualNeeded) replaceExpectModifier(actualNeeded)
@@ -330,19 +324,19 @@ private fun KtPsiFactory.generateFunction(
} }
private fun KtPsiFactory.generateProperty( private fun KtPsiFactory.generateProperty(
project: Project, project: Project,
expectedProperty: KtProperty, expectedProperty: KtProperty,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
actualNeeded: Boolean actualNeeded: Boolean
): KtProperty { ): KtProperty {
val body = buildString { val body = buildString {
append("\nget()") append("\nget()")
append(" = ") append(" = ")
append(getFunctionBodyTextFromTemplate( append(getFunctionBodyTextFromTemplate(
project, project,
TemplateKind.FUNCTION, TemplateKind.FUNCTION,
descriptor.name.asString(), descriptor.name.asString(),
descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "" descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: ""
)) ))
if (descriptor.isVar) { if (descriptor.isVar) {
append("\nset(value) {}") append("\nset(value) {}")