Create from Usage: Secondary constructor support
This commit is contained in:
@@ -207,6 +207,10 @@ public class JetPsiFactory(private val project: Project) {
|
||||
return createDeclaration(funDecl)
|
||||
}
|
||||
|
||||
public fun createSecondaryConstructor(decl: String): JetSecondaryConstructor {
|
||||
return createClass("class Foo {\n $decl \n}").getSecondaryConstructors().first()
|
||||
}
|
||||
|
||||
public fun createModifierList(modifier: JetKeywordToken): JetModifierList {
|
||||
return createModifierList(modifier.getValue())
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
//To change body of created constructors use File | Settings | File Templates.
|
||||
@@ -0,0 +1,28 @@
|
||||
<html>
|
||||
<body>
|
||||
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used for filling the body of a Kotlin secondary
|
||||
constructor each time it is generated by the program, e.g. when using the <b>Create secondary constructor from Usage</b> intention action.<br>
|
||||
The template is editable. Along with Kotlin expressions and comments, you can also use the predefined variables
|
||||
that will be then expanded into the corresponding values.</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
|
||||
<tr>
|
||||
<td colspan="3"><font face="verdana" size="-1">Predefined variables will take the following values:</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${CLASS_NAME}</i></b></font></nobr></td>
|
||||
<td width="10"> </td>
|
||||
<td valign="top"><font face="verdana" size="-1">qualified name of the class where function is created</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${SIMPLE_CLASS_NAME}</i></b></font></nobr></td>
|
||||
<td width="10"> </td>
|
||||
<td valign="top"><font face="verdana" size="-1">non-qualified name of the class where function is implemented</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
+108
-82
@@ -16,73 +16,61 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||
import com.intellij.codeInsight.template.*
|
||||
import com.intellij.codeInsight.template.impl.TemplateImpl
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||
import com.intellij.ide.fileTemplates.FileTemplate
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ScrollType
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import kotlin.properties.Delegates
|
||||
import java.util.LinkedHashSet
|
||||
import java.util.Collections
|
||||
import java.util.HashMap
|
||||
import java.util.ArrayList
|
||||
import java.util.Properties
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import java.util.LinkedHashMap
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassKind
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import com.intellij.openapi.editor.ScrollType
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiMember
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||
import com.intellij.psi.PsiMethodCallExpression
|
||||
import com.intellij.psi.PsiExpressionStatement
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassKind
|
||||
import org.jetbrains.kotlin.idea.refactoring.*
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import com.intellij.openapi.ui.*
|
||||
import com.intellij.codeInsight.template.impl.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.util.application.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
|
||||
private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt"
|
||||
private val TEMPLATE_FROM_USAGE_SECONDARY_CONSTRUCTOR_BODY = "New Kotlin Secondary Constructor Body.kt"
|
||||
private val ATTRIBUTE_FUNCTION_NAME = "FUNCTION_NAME"
|
||||
|
||||
/**
|
||||
@@ -322,8 +310,9 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
skipReturnType = when (callableInfo.kind) {
|
||||
CallableKind.FUNCTION ->
|
||||
returnTypeCandidate?.theType?.isUnit() ?: false
|
||||
CallableKind.CONSTRUCTOR ->
|
||||
CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR ->
|
||||
callableInfo.returnTypeInfo == TypeInfo.Empty || returnTypeCandidate?.theType?.isAny() ?: false
|
||||
CallableKind.SECONDARY_CONSTRUCTOR -> true
|
||||
CallableKind.PROPERTY -> containingElement is JetBlockExpression
|
||||
}
|
||||
|
||||
@@ -437,7 +426,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
|
||||
val ownerTypeString = if (isExtension) "${receiverTypeCandidate!!.renderedType!!}." else ""
|
||||
|
||||
val classKind = (callableInfo as? ConstructorInfo)?.classInfo?.kind
|
||||
val classKind = (callableInfo as? PrimaryConstructorInfo)?.classInfo?.kind
|
||||
|
||||
fun renderParamList(): String {
|
||||
val prefix = if (classKind == ClassKind.ANNOTATION_CLASS) "val " else ""
|
||||
@@ -446,7 +435,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
|
||||
val paramList = when (callableInfo.kind) {
|
||||
CallableKind.FUNCTION, CallableKind.CONSTRUCTOR -> renderParamList()
|
||||
CallableKind.FUNCTION, CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR, CallableKind.SECONDARY_CONSTRUCTOR ->
|
||||
renderParamList()
|
||||
CallableKind.PROPERTY -> ""
|
||||
}
|
||||
val returnTypeString = if (skipReturnType || assignmentToReplace != null) "" else ": Any"
|
||||
@@ -455,20 +445,27 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
val psiFactory = JetPsiFactory(currentFile)
|
||||
|
||||
val modifiers =
|
||||
if (containingElement is JetClassOrObject && containingElement.isAncestor(config.originalElement))
|
||||
if (containingElement is JetClassOrObject
|
||||
&& containingElement.isAncestor(config.originalElement)
|
||||
&& callableInfo.kind != CallableKind.SECONDARY_CONSTRUCTOR)
|
||||
"private "
|
||||
else ""
|
||||
|
||||
val declaration : JetNamedDeclaration = when (callableInfo.kind) {
|
||||
CallableKind.FUNCTION -> {
|
||||
CallableKind.FUNCTION, CallableKind.SECONDARY_CONSTRUCTOR -> {
|
||||
val body = when {
|
||||
containingElement is JetClass && containingElement.isTrait() && !config.isExtension -> ""
|
||||
else -> "{}"
|
||||
}
|
||||
psiFactory.createFunction("${modifiers}fun<> $header $body")
|
||||
if (callableInfo.kind == CallableKind.FUNCTION) {
|
||||
psiFactory.createFunction("${modifiers}fun<> $header $body")
|
||||
}
|
||||
else {
|
||||
psiFactory.createSecondaryConstructor("${modifiers}constructor$paramList $body")
|
||||
}
|
||||
}
|
||||
CallableKind.CONSTRUCTOR -> {
|
||||
with((callableInfo as ConstructorInfo).classInfo) {
|
||||
CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR -> {
|
||||
with((callableInfo as PrimaryConstructorInfo).classInfo) {
|
||||
val classBody = when (kind) {
|
||||
ClassKind.ANNOTATION_CLASS, ClassKind.ENUM_ENTRY -> ""
|
||||
else -> "{\n\n}"
|
||||
@@ -557,23 +554,19 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
|
||||
containingElement is JetFile -> containingElement.add(declaration) as JetNamedDeclaration
|
||||
|
||||
containingElement is PsiClass -> jetFileToEdit.add(declaration) as JetNamedDeclaration
|
||||
containingElement is PsiClass -> {
|
||||
if (declaration is JetSecondaryConstructor) {
|
||||
val wrappingClass = psiFactory.createClass("class ${containingElement.getName()} {\n}")
|
||||
addDeclarationToClassOrObject(wrappingClass, declaration, psiFactory)
|
||||
(jetFileToEdit.add(wrappingClass) as JetClass).getDeclarations().first() as JetNamedDeclaration
|
||||
}
|
||||
else {
|
||||
jetFileToEdit.add(declaration) as JetNamedDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
containingElement is JetClassOrObject -> {
|
||||
var classBody = containingElement.getBody()
|
||||
if (classBody == null) {
|
||||
classBody = containingElement.add(psiFactory.createEmptyClassBody()) as JetClassBody
|
||||
containingElement.addBefore(psiFactory.createWhiteSpace(), classBody)
|
||||
}
|
||||
|
||||
if (declaration is JetNamedFunction) {
|
||||
val anchor = PsiTreeUtil.skipSiblingsBackward(
|
||||
classBody!!.getRBrace() ?: classBody!!.getLastChild()!!,
|
||||
javaClass<PsiWhiteSpace>()
|
||||
)
|
||||
classBody.addAfter(declaration, anchor) as JetNamedDeclaration
|
||||
}
|
||||
else classBody.addAfter(declaration, classBody!!.getLBrace()!!) as JetNamedDeclaration
|
||||
addDeclarationToClassOrObject(containingElement, declaration, psiFactory)
|
||||
}
|
||||
else -> throw AssertionError("Invalid containing element: ${containingElement.getText()}")
|
||||
}
|
||||
@@ -590,6 +583,25 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDeclarationToClassOrObject(classOrObject: JetClassOrObject,
|
||||
declaration: JetNamedDeclaration,
|
||||
psiFactory: JetPsiFactory): JetNamedDeclaration {
|
||||
var classBody = classOrObject.getBody()
|
||||
if (classBody == null) {
|
||||
classBody = classOrObject.add(psiFactory.createEmptyClassBody()) as JetClassBody
|
||||
classOrObject.addBefore(psiFactory.createWhiteSpace(), classBody)
|
||||
}
|
||||
|
||||
return if (declaration is JetNamedFunction) {
|
||||
val anchor = PsiTreeUtil.skipSiblingsBackward(
|
||||
classBody!!.getRBrace() ?: classBody!!.getLastChild()!!,
|
||||
javaClass<PsiWhiteSpace>()
|
||||
)
|
||||
classBody.addAfter(declaration, anchor) as JetNamedDeclaration
|
||||
}
|
||||
else classBody.addAfter(declaration, classBody!!.getLBrace()!!) as JetNamedDeclaration
|
||||
}
|
||||
|
||||
private fun getTypeParameterRenames(scope: JetScope): Map<TypeParameterDescriptor, String> {
|
||||
val allTypeParametersNotInScope = LinkedHashSet<TypeParameterDescriptor>()
|
||||
|
||||
@@ -660,17 +672,24 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
return typeRefsToShorten
|
||||
}
|
||||
|
||||
private fun setupFunctionBody(func: JetNamedFunction) {
|
||||
private fun setupFunctionBody(func: JetFunction) {
|
||||
val oldBody = func.getBodyExpression() ?: return
|
||||
|
||||
val fileTemplate = FileTemplateManager.getInstance()!!.getCodeTemplate(TEMPLATE_FROM_USAGE_FUNCTION_BODY)
|
||||
val templateName = when (func) {
|
||||
is JetSecondaryConstructor -> TEMPLATE_FROM_USAGE_SECONDARY_CONSTRUCTOR_BODY
|
||||
is JetNamedFunction -> TEMPLATE_FROM_USAGE_FUNCTION_BODY
|
||||
else -> throw AssertionError("Unexpected declaration: " + JetPsiUtil.getElementTextWithContext(func))
|
||||
}
|
||||
val fileTemplate = FileTemplateManager.getInstance()!!.getCodeTemplate(templateName)
|
||||
val properties = Properties()
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_RETURN_TYPE, if (skipReturnType) "Unit" else func.getTypeReference()!!.getText())
|
||||
receiverClassDescriptor?.let {
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_CLASS_NAME, DescriptorUtils.getFqName(it).asString())
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_SIMPLE_CLASS_NAME, it.getName().asString())
|
||||
}
|
||||
properties.setProperty(ATTRIBUTE_FUNCTION_NAME, callableInfo.name)
|
||||
if (callableInfo.name.isNotEmpty()) {
|
||||
properties.setProperty(ATTRIBUTE_FUNCTION_NAME, callableInfo.name)
|
||||
}
|
||||
|
||||
val bodyText = try {
|
||||
fileTemplate!!.getText(properties)
|
||||
@@ -766,7 +785,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
val expression = TypeParameterListExpression(
|
||||
mandatoryTypeParameters,
|
||||
typeParameterMap,
|
||||
callableInfo.kind != CallableKind.CONSTRUCTOR
|
||||
callableInfo.kind != CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR
|
||||
)
|
||||
builder.replaceElement(typeParameterList, expression, false)
|
||||
return expression
|
||||
@@ -831,8 +850,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
|
||||
return when (adjustedDeclaration) {
|
||||
is JetNamedFunction -> {
|
||||
createJavaMethod(adjustedDeclaration, targetClass)
|
||||
is JetNamedFunction, is JetSecondaryConstructor -> {
|
||||
createJavaMethod(adjustedDeclaration as JetFunction, targetClass)
|
||||
}
|
||||
is JetProperty -> {
|
||||
createJavaField(adjustedDeclaration, targetClass)
|
||||
@@ -859,7 +878,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
|
||||
val needStatic = when (callableInfo) {
|
||||
is ConstructorInfo -> with(callableInfo.classInfo) {
|
||||
is PrimaryConstructorInfo -> with(callableInfo.classInfo) {
|
||||
!inner && kind != ClassKind.ENUM_ENTRY && kind != ClassKind.ENUM_CLASS
|
||||
}
|
||||
else -> callableInfo.receiverTypeInfo.staticContextRequired
|
||||
@@ -896,7 +915,12 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
val caretModel = containingFileEditor.getCaretModel()
|
||||
val selectionModel = containingFileEditor.getSelectionModel()
|
||||
|
||||
caretModel.moveToOffset(declaration.getNameIdentifier().getTextRange().getEndOffset())
|
||||
if (declaration is JetSecondaryConstructor) {
|
||||
caretModel.moveToOffset(declaration.getConstructorKeyword().getTextRange().getEndOffset())
|
||||
}
|
||||
else {
|
||||
caretModel.moveToOffset(declaration.getNameIdentifier()!!.getTextRange().getEndOffset())
|
||||
}
|
||||
|
||||
fun positionBetween(left: PsiElement, right: PsiElement) {
|
||||
val from = left.siblings(withItself = false, forward = true).firstOrNull { it !is PsiWhiteSpace } ?: return
|
||||
@@ -908,8 +932,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
}
|
||||
|
||||
when (declaration) {
|
||||
is JetNamedFunction -> {
|
||||
(declaration.getBodyExpression() as? JetBlockExpression)?.let { positionBetween(it.getLBrace(), it.getRBrace()) }
|
||||
is JetNamedFunction, is JetSecondaryConstructor -> {
|
||||
((declaration as JetFunction).getBodyExpression() as? JetBlockExpression)?.let {
|
||||
positionBetween(it.getLBrace(), it.getRBrace())
|
||||
}
|
||||
}
|
||||
is JetClassOrObject -> {
|
||||
caretModel.moveToOffset(declaration.getTextRange().getStartOffset())
|
||||
@@ -995,8 +1021,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
|
||||
runWriteAction {
|
||||
// file templates
|
||||
if (newDeclaration is JetNamedFunction) {
|
||||
setupFunctionBody(newDeclaration)
|
||||
if (newDeclaration is JetNamedFunction || newDeclaration is JetSecondaryConstructor) {
|
||||
setupFunctionBody(newDeclaration as JetFunction)
|
||||
}
|
||||
|
||||
val callElement = config.originalElement as? JetCallElement
|
||||
|
||||
+12
-3
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -119,7 +120,8 @@ class ParameterInfo(
|
||||
|
||||
enum class CallableKind {
|
||||
FUNCTION
|
||||
CONSTRUCTOR
|
||||
CLASS_WITH_PRIMARY_CONSTRUCTOR
|
||||
SECONDARY_CONSTRUCTOR
|
||||
PROPERTY
|
||||
}
|
||||
|
||||
@@ -144,13 +146,20 @@ class FunctionInfo(name: String,
|
||||
override val kind: CallableKind get() = CallableKind.FUNCTION
|
||||
}
|
||||
|
||||
class ConstructorInfo(val classInfo: ClassInfo, expectedTypeInfo: TypeInfo): CallableInfo(
|
||||
class PrimaryConstructorInfo(val classInfo: ClassInfo, expectedTypeInfo: TypeInfo): CallableInfo(
|
||||
classInfo.name, TypeInfo.Empty, expectedTypeInfo.forceNotNull(), Collections.emptyList(), classInfo.typeArguments
|
||||
) {
|
||||
override val kind: CallableKind get() = CallableKind.CONSTRUCTOR
|
||||
override val kind: CallableKind get() = CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR
|
||||
override val parameterInfos: List<ParameterInfo> get() = classInfo.parameterInfos
|
||||
}
|
||||
|
||||
class SecondaryConstructorInfo(
|
||||
override val parameterInfos: List<ParameterInfo>,
|
||||
val targetClass: PsiElement
|
||||
): CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList()) {
|
||||
override val kind: CallableKind get() = CallableKind.SECONDARY_CONSTRUCTOR
|
||||
}
|
||||
|
||||
class PropertyInfo(name: String,
|
||||
receiverTypeInfo: TypeInfo,
|
||||
returnTypeInfo: TypeInfo,
|
||||
|
||||
+18
-17
@@ -16,25 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
|
||||
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
|
||||
import org.jetbrains.kotlin.psi.JetClassBody
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import java.util.Collections
|
||||
import java.util.HashSet
|
||||
|
||||
public class CreateCallableFromUsageFix(
|
||||
originalExpression: JetExpression,
|
||||
@@ -64,9 +59,10 @@ public class CreateCallableFromUsageFix(
|
||||
val kind = when (it.kind) {
|
||||
CallableKind.FUNCTION -> "function"
|
||||
CallableKind.PROPERTY -> "property"
|
||||
CallableKind.SECONDARY_CONSTRUCTOR -> "secondary constructor"
|
||||
else -> throw AssertionError("Unexpected callable info: $it")
|
||||
}
|
||||
"$kind '${it.name}'"
|
||||
if (it.name.isNotEmpty()) "$kind '${it.name}'" else kind
|
||||
}
|
||||
return JetBundle.message(
|
||||
"create.0.from.usage",
|
||||
@@ -114,6 +110,11 @@ public class CreateCallableFromUsageFix(
|
||||
CommandProcessor.getInstance().executeCommand(project, { callableBuilder.build() }, getText(), null)
|
||||
}
|
||||
|
||||
if (callableInfo is SecondaryConstructorInfo) {
|
||||
runBuilder(CallablePlacement.NoReceiver(callableInfo.targetClass))
|
||||
return
|
||||
}
|
||||
|
||||
val popupTitle = JetBundle.message("choose.target.class.or.trait.title")
|
||||
val receiverTypeCandidates = callableBuilder.computeTypeCandidates(callableInfo.receiverTypeInfo)
|
||||
if (receiverTypeCandidates.isNotEmpty()) {
|
||||
|
||||
+2
-7
@@ -26,14 +26,8 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import org.jetbrains.kotlin.idea.JetFileType
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ConstructorInfo
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableBuilderConfiguration
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.createBuilder
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallablePlacement
|
||||
import org.jetbrains.kotlin.idea.refactoring.getOrCreateKotlinFile
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassKind.*
|
||||
import com.intellij.psi.PsiPackage
|
||||
@@ -45,6 +39,7 @@ import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import com.intellij.psi.PsiMember
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
||||
|
||||
enum class ClassKind(val keyword: String, val description: String) {
|
||||
PLAIN_CLASS: ClassKind("class", "class")
|
||||
@@ -124,7 +119,7 @@ public class CreateClassFromUsageFix(
|
||||
else -> throw AssertionError("Unexpected element: " + targetParent.getText())
|
||||
} ?: return
|
||||
|
||||
val constructorInfo = ConstructorInfo(classInfo, expectedTypeInfo)
|
||||
val constructorInfo = PrimaryConstructorInfo(classInfo, expectedTypeInfo)
|
||||
val builder = CallableBuilderConfiguration(
|
||||
Collections.singletonList(constructorInfo), element as JetElement, file, editor, false, kind == PLAIN_CLASS || kind == TRAIT
|
||||
).createBuilder()
|
||||
|
||||
@@ -481,7 +481,7 @@ private fun copyTypeParameters<T: PsiTypeParameterListOwner>(
|
||||
}
|
||||
}
|
||||
|
||||
public fun createJavaMethod(function: JetNamedFunction, targetClass: PsiClass): PsiMethod {
|
||||
public fun createJavaMethod(function: JetFunction, targetClass: PsiClass): PsiMethod {
|
||||
val template = LightClassUtil.getLightClassMethod(function)
|
||||
?: throw AssertionError("Can't generate light method: ${JetPsiUtil.getElementTextWithContext(function)}")
|
||||
return createJavaMethod(template, targetClass)
|
||||
|
||||
Reference in New Issue
Block a user