Override/Implement: Use function body template when generating functions with default body
#KT-11807 Fixed
This commit is contained in:
+17
-6
@@ -24,6 +24,8 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.TemplateKind
|
||||
import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate
|
||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -115,7 +117,7 @@ private fun generateProperty(project: Project, descriptor: PropertyDescriptor, b
|
||||
val body = buildString {
|
||||
append("\nget()")
|
||||
append(" = ")
|
||||
append(generateUnsupportedOrSuperCall(descriptor, bodyType))
|
||||
append(generateUnsupportedOrSuperCall(project, descriptor, bodyType))
|
||||
if (descriptor.isVar) {
|
||||
append("\nset(value) {}")
|
||||
}
|
||||
@@ -139,17 +141,26 @@ private fun generateFunction(project: Project, descriptor: FunctionDescriptor, b
|
||||
val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
|
||||
|
||||
val body = if (bodyType != OverrideMemberChooserObject.BodyType.NO_BODY) {
|
||||
val delegation = generateUnsupportedOrSuperCall(descriptor, bodyType)
|
||||
"{" + (if (returnsNotUnit && bodyType != OverrideMemberChooserObject.BodyType.EMPTY) "return " else "") + delegation + "}"
|
||||
val delegation = generateUnsupportedOrSuperCall(project, descriptor, bodyType)
|
||||
"{" + (if (returnsNotUnit && bodyType != OverrideMemberChooserObject.BodyType.EMPTY) "return " else "") + delegation + "\n}"
|
||||
}
|
||||
else ""
|
||||
|
||||
return KtPsiFactory(project).createFunction(OVERRIDE_RENDERER.render(newDescriptor) + body)
|
||||
}
|
||||
|
||||
fun generateUnsupportedOrSuperCall(descriptor: CallableMemberDescriptor, bodyType: OverrideMemberChooserObject.BodyType): String {
|
||||
fun generateUnsupportedOrSuperCall(
|
||||
project: Project,
|
||||
descriptor: CallableMemberDescriptor,
|
||||
bodyType: OverrideMemberChooserObject.BodyType
|
||||
): String {
|
||||
if (bodyType == OverrideMemberChooserObject.BodyType.EMPTY) {
|
||||
return "throw UnsupportedOperationException()"
|
||||
if (descriptor !is FunctionDescriptor) return "throw UnsupportedOperationException()"
|
||||
return getFunctionBodyTextFromTemplate(project,
|
||||
TemplateKind.FUNCTION,
|
||||
descriptor.name.asString(),
|
||||
descriptor.returnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "Unit",
|
||||
null)
|
||||
}
|
||||
else {
|
||||
return buildString {
|
||||
@@ -165,7 +176,7 @@ fun generateUnsupportedOrSuperCall(descriptor: CallableMemberDescriptor, bodyTyp
|
||||
val renderedName = it.name.render()
|
||||
if (it.varargElementType != null) "*$renderedName" else renderedName
|
||||
}
|
||||
paramTexts.joinTo(this, prefix="(", postfix=")")
|
||||
paramTexts.joinTo(this, prefix = "(", postfix = ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
|
||||
import com.intellij.ide.fileTemplates.FileTemplate
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.util.*
|
||||
|
||||
private val FUNCTION_BODY_TEMPLATE = "New Kotlin Function Body.kt"
|
||||
private val SECONDARY_CONSTRUCTOR_BODY_TEMPLATE = "New Kotlin Secondary Constructor Body.kt"
|
||||
private val ATTRIBUTE_FUNCTION_NAME = "FUNCTION_NAME"
|
||||
|
||||
enum class TemplateKind(val templateFileName: String) {
|
||||
FUNCTION(FUNCTION_BODY_TEMPLATE), SECONDARY_CONSTRUCTOR(SECONDARY_CONSTRUCTOR_BODY_TEMPLATE)
|
||||
}
|
||||
|
||||
fun getFunctionBodyTextFromTemplate(
|
||||
project: Project,
|
||||
kind: TemplateKind,
|
||||
name: String?,
|
||||
returnType: String,
|
||||
classFqName: FqName? = null
|
||||
): String {
|
||||
val fileTemplate = FileTemplateManager.getInstance(project)!!.getCodeTemplate(kind.templateFileName)
|
||||
|
||||
val properties = Properties()
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, returnType)
|
||||
if (classFqName != null) {
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, classFqName.asString())
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, classFqName.shortName().asString())
|
||||
}
|
||||
if (name != null) {
|
||||
properties.setProperty(ATTRIBUTE_FUNCTION_NAME, name)
|
||||
}
|
||||
|
||||
return try {
|
||||
fileTemplate!!.getText(properties)
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
// TODO: This is dangerous.
|
||||
// Is there any way to avoid catching all exceptions?
|
||||
throw IncorrectOperationException("Failed to parse file template", e)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user