diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt index b6f3833a5e1..99b7fa37cb0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt @@ -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()) } diff --git a/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.ft b/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.ft new file mode 100644 index 00000000000..488cc7226de --- /dev/null +++ b/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.ft @@ -0,0 +1 @@ +//To change body of created constructors use File | Settings | File Templates. \ No newline at end of file diff --git a/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.html b/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.html new file mode 100644 index 00000000000..0c35380ba9d --- /dev/null +++ b/idea/resources/fileTemplates/code/New Kotlin Secondary Constructor Body.kt.html @@ -0,0 +1,28 @@ + + + + + + +
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 Create secondary constructor from Usage intention action.
+ 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.
+
+ + + + + + + + + + + + + + +
Predefined variables will take the following values:
${CLASS_NAME} qualified name of the class where function is created
${SIMPLE_CLASS_NAME} non-qualified name of the class where function is implemented
+ + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt index 773023a536d..8a82843ab51 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt @@ -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() - ) - 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() + ) + classBody.addAfter(declaration, anchor) as JetNamedDeclaration + } + else classBody.addAfter(declaration, classBody!!.getLBrace()!!) as JetNamedDeclaration + } + private fun getTypeParameterRenames(scope: JetScope): Map { val allTypeParametersNotInScope = LinkedHashSet() @@ -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 diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableInfo.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableInfo.kt index 9c79476b2a6..c457180069e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableInfo.kt @@ -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 get() = classInfo.parameterInfos } +class SecondaryConstructorInfo( + override val parameterInfos: List, + 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, diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromUsageFix.kt index cb4e90f62fa..63fb1396bc0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromUsageFix.kt @@ -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()) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt index 728c4c34d49..3e2e7017310 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt @@ -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() diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt index 3d19d88efc5..dfa3543cd1b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt @@ -481,7 +481,7 @@ private fun copyTypeParameters( } } -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)