Skip to content

Commit 15dddf3

Browse files
committed
Create from Usage: Secondary constructor support
1 parent 1167532 commit 15dddf3

File tree

8 files changed

+172
-108
lines changed

8 files changed

+172
-108
lines changed

compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ public class JetPsiFactory(private val project: Project) {
207207
return createDeclaration(funDecl)
208208
}
209209

210+
public fun createSecondaryConstructor(decl: String): JetSecondaryConstructor {
211+
return createClass("class Foo {\n $decl \n}").getSecondaryConstructors().first()
212+
}
213+
210214
public fun createModifierList(modifier: JetKeywordToken): JetModifierList {
211215
return createModifierList(modifier.getValue())
212216
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//To change body of created constructors use File | Settings | File Templates.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<html>
2+
<body>
3+
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
4+
<tr>
5+
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used for filling the body of a Kotlin secondary
6+
constructor each time it is generated by the program, e.g. when using the <b>Create secondary constructor from Usage</b> intention action.<br>
7+
The template is editable. Along with Kotlin expressions and comments, you can also use the predefined variables
8+
that will be then expanded into the corresponding values.</font>
9+
</td>
10+
</tr>
11+
</table>
12+
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
13+
<tr>
14+
<td colspan="3"><font face="verdana" size="-1">Predefined variables will take the following values:</font></td>
15+
</tr>
16+
<tr>
17+
<td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${CLASS_NAME}</i></b></font></nobr></td>
18+
<td width="10">&nbsp;</td>
19+
<td valign="top"><font face="verdana" size="-1">qualified name of the class where function is created</font></td>
20+
</tr>
21+
<tr>
22+
<td valign="top"><nobr><font face="verdana" size="-2" color="#7F0000"><b><i>${SIMPLE_CLASS_NAME}</i></b></font></nobr></td>
23+
<td width="10">&nbsp;</td>
24+
<td valign="top"><font face="verdana" size="-1">non-qualified name of the class where function is implemented</font></td>
25+
</tr>
26+
</table>
27+
</body>
28+
</html>

idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt

Lines changed: 108 additions & 82 deletions
Large diffs are not rendered by default.

idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/CallableInfo.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
1818

19+
import com.intellij.psi.PsiElement
1920
import java.util.Collections
2021
import org.jetbrains.kotlin.psi.JetExpression
2122
import org.jetbrains.kotlin.types.Variance
@@ -119,7 +120,8 @@ class ParameterInfo(
119120

120121
enum class CallableKind {
121122
FUNCTION
122-
CONSTRUCTOR
123+
CLASS_WITH_PRIMARY_CONSTRUCTOR
124+
SECONDARY_CONSTRUCTOR
123125
PROPERTY
124126
}
125127

@@ -144,13 +146,20 @@ class FunctionInfo(name: String,
144146
override val kind: CallableKind get() = CallableKind.FUNCTION
145147
}
146148

147-
class ConstructorInfo(val classInfo: ClassInfo, expectedTypeInfo: TypeInfo): CallableInfo(
149+
class PrimaryConstructorInfo(val classInfo: ClassInfo, expectedTypeInfo: TypeInfo): CallableInfo(
148150
classInfo.name, TypeInfo.Empty, expectedTypeInfo.forceNotNull(), Collections.emptyList(), classInfo.typeArguments
149151
) {
150-
override val kind: CallableKind get() = CallableKind.CONSTRUCTOR
152+
override val kind: CallableKind get() = CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR
151153
override val parameterInfos: List<ParameterInfo> get() = classInfo.parameterInfos
152154
}
153155

156+
class SecondaryConstructorInfo(
157+
override val parameterInfos: List<ParameterInfo>,
158+
val targetClass: PsiElement
159+
): CallableInfo("", TypeInfo.Empty, TypeInfo.Empty, Collections.emptyList(), Collections.emptyList()) {
160+
override val kind: CallableKind get() = CallableKind.SECONDARY_CONSTRUCTOR
161+
}
162+
154163
class PropertyInfo(name: String,
155164
receiverTypeInfo: TypeInfo,
156165
returnTypeInfo: TypeInfo,

idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromUsageFix.kt

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,20 @@
1616

1717
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable
1818

19-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
20-
import org.jetbrains.kotlin.psi.JetFile
19+
import com.intellij.openapi.command.CommandProcessor
2120
import com.intellij.openapi.editor.Editor
22-
import org.jetbrains.kotlin.idea.JetBundle
2321
import com.intellij.openapi.project.Project
24-
import com.intellij.openapi.command.CommandProcessor
22+
import com.intellij.psi.PsiClass
23+
import com.intellij.psi.PsiElement
24+
import org.jetbrains.kotlin.idea.JetBundle
2525
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
26-
import org.jetbrains.kotlin.psi.JetClassOrObject
27-
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
28-
import org.jetbrains.kotlin.psi.JetClassBody
26+
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase
2927
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
30-
import org.jetbrains.kotlin.psi.JetExpression
31-
import java.util.HashSet
32-
import org.jetbrains.kotlin.psi.JetElement
33-
import com.intellij.psi.PsiClass
34-
import java.util.Collections
35-
import org.jetbrains.kotlin.psi.JetPsiUtil
3628
import org.jetbrains.kotlin.idea.refactoring.canRefactor
37-
import com.intellij.psi.PsiElement
29+
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
30+
import org.jetbrains.kotlin.psi.*
31+
import java.util.Collections
32+
import java.util.HashSet
3833

3934
public class CreateCallableFromUsageFix(
4035
originalExpression: JetExpression,
@@ -64,9 +59,10 @@ public class CreateCallableFromUsageFix(
6459
val kind = when (it.kind) {
6560
CallableKind.FUNCTION -> "function"
6661
CallableKind.PROPERTY -> "property"
62+
CallableKind.SECONDARY_CONSTRUCTOR -> "secondary constructor"
6763
else -> throw AssertionError("Unexpected callable info: $it")
6864
}
69-
"$kind '${it.name}'"
65+
if (it.name.isNotEmpty()) "$kind '${it.name}'" else kind
7066
}
7167
return JetBundle.message(
7268
"create.0.from.usage",
@@ -114,6 +110,11 @@ public class CreateCallableFromUsageFix(
114110
CommandProcessor.getInstance().executeCommand(project, { callableBuilder.build() }, getText(), null)
115111
}
116112

113+
if (callableInfo is SecondaryConstructorInfo) {
114+
runBuilder(CallablePlacement.NoReceiver(callableInfo.targetClass))
115+
return
116+
}
117+
117118
val popupTitle = JetBundle.message("choose.target.class.or.trait.title")
118119
val receiverTypeCandidates = callableBuilder.computeTypeCandidates(callableInfo.receiverTypeInfo)
119120
if (receiverTypeCandidates.isNotEmpty()) {

idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,8 @@ import com.intellij.psi.PsiElement
2626
import com.intellij.psi.PsiDirectory
2727
import org.jetbrains.kotlin.idea.JetFileType
2828
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
29-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
30-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
31-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ConstructorInfo
32-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallableBuilderConfiguration
3329
import java.util.Collections
34-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.createBuilder
3530
import com.intellij.openapi.command.CommandProcessor
36-
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.CallablePlacement
3731
import org.jetbrains.kotlin.idea.refactoring.getOrCreateKotlinFile
3832
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassKind.*
3933
import com.intellij.psi.PsiPackage
@@ -45,6 +39,7 @@ import org.jetbrains.kotlin.idea.refactoring.canRefactor
4539
import com.intellij.psi.PsiMember
4640
import com.intellij.psi.PsiClass
4741
import com.intellij.psi.PsiFile
42+
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
4843

4944
enum class ClassKind(val keyword: String, val description: String) {
5045
PLAIN_CLASS: ClassKind("class", "class")
@@ -124,7 +119,7 @@ public class CreateClassFromUsageFix(
124119
else -> throw AssertionError("Unexpected element: " + targetParent.getText())
125120
} ?: return
126121

127-
val constructorInfo = ConstructorInfo(classInfo, expectedTypeInfo)
122+
val constructorInfo = PrimaryConstructorInfo(classInfo, expectedTypeInfo)
128123
val builder = CallableBuilderConfiguration(
129124
Collections.singletonList(constructorInfo), element as JetElement, file, editor, false, kind == PLAIN_CLASS || kind == TRAIT
130125
).createBuilder()

idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ private fun copyTypeParameters<T: PsiTypeParameterListOwner>(
481481
}
482482
}
483483

484-
public fun createJavaMethod(function: JetNamedFunction, targetClass: PsiClass): PsiMethod {
484+
public fun createJavaMethod(function: JetFunction, targetClass: PsiClass): PsiMethod {
485485
val template = LightClassUtil.getLightClassMethod(function)
486486
?: throw AssertionError("Can't generate light method: ${JetPsiUtil.getElementTextWithContext(function)}")
487487
return createJavaMethod(template, targetClass)

0 commit comments

Comments
 (0)