diff --git a/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/after.kt.template b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/after.kt.template
new file mode 100644
index 00000000000..3d79bccf651
--- /dev/null
+++ b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/after.kt.template
@@ -0,0 +1 @@
+class Foo(n: Int, val s: String)
diff --git a/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/before.kt.template b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/before.kt.template
new file mode 100644
index 00000000000..35b4b19e713
--- /dev/null
+++ b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/before.kt.template
@@ -0,0 +1 @@
+class Foo(n: Int, s: String)
diff --git a/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/description.html b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/description.html
new file mode 100644
index 00000000000..b2c8931c243
--- /dev/null
+++ b/idea/resources/intentionDescriptions/AddValVarToConstructorParameterIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention adds val/var keyword to the primary constructor parameter effectively making it a property.
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index f4a68f12db9..581fbf9950e 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1115,6 +1115,11 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterIntention
+ Kotlin
+
+
(KtParameter::class.java,
+ "Add val/var to primary constructor parameter") {
+ override fun applicabilityRange(element: KtParameter): TextRange? {
+ if (element.valOrVarKeyword != null) return null
+ if ((element.parent as? KtParameterList)?.parent !is KtPrimaryConstructor) return null
+ text = "Add val/var to parameter '${element.name ?: ""}'"
+ return element.nameIdentifier?.textRange
+ }
+
+ override fun applyTo(element: KtParameter, editor: Editor) {
+ val project = element.project
+
+ element.addAfter(KtPsiFactory(project).createValKeyword(), null)
+
+ val parameter = element.createSmartPointer().let {
+ PsiDocumentManager.getInstance(project).commitAllDocuments()
+ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
+ it.element
+ } ?: return
+
+ TemplateBuilderImpl(parameter)
+ .apply { replaceElement(parameter.valOrVarKeyword!!, ValVarExpression) }
+ .buildInlineTemplate()
+ .let { TemplateManager.getInstance(project).startTemplate(editor, it) }
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/templateExpressions.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/templateExpressions.kt
index d25f64563c7..ecc938aca16 100644
--- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/templateExpressions.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/templateExpressions.kt
@@ -184,13 +184,3 @@ internal class TypeParameterListExpression(private val mandatoryTypeParameters:
// do not offer the user any choices
override fun calculateLookupItems(context: ExpressionContext?) = arrayOf()
}
-
-internal object ValVarExpression: Expression() {
- private val cachedLookupElements = listOf("val", "var").map { LookupElementBuilder.create(it) }.toTypedArray()
-
- override fun calculateResult(context: ExpressionContext?): Result? = TextResult("val")
-
- override fun calculateQuickResult(context: ExpressionContext?): Result? = calculateResult(context)
-
- override fun calculateLookupItems(context: ExpressionContext?): Array? = cachedLookupElements
-}
diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/ValVarExpression.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/ValVarExpression.kt
new file mode 100644
index 00000000000..c75bc92512b
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/ValVarExpression.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2015 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.refactoring
+
+import com.intellij.codeInsight.lookup.LookupElement
+import com.intellij.codeInsight.lookup.LookupElementBuilder
+import com.intellij.codeInsight.template.Expression
+import com.intellij.codeInsight.template.ExpressionContext
+import com.intellij.codeInsight.template.Result
+import com.intellij.codeInsight.template.TextResult
+
+object ValVarExpression: Expression() {
+ private val cachedLookupElements = listOf("val", "var").map { LookupElementBuilder.create(it) }.toTypedArray()
+
+ override fun calculateResult(context: ExpressionContext?): Result? = TextResult("val")
+
+ override fun calculateQuickResult(context: ExpressionContext?): Result? = calculateResult(context)
+
+ override fun calculateLookupItems(context: ExpressionContext?): Array? = cachedLookupElements
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/.intention b/idea/testData/intentions/addValOrVar/.intention
new file mode 100644
index 00000000000..6c3841003d3
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.AddValVarToConstructorParameterIntention
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/addVal.kt b/idea/testData/intentions/addValOrVar/addVal.kt
new file mode 100644
index 00000000000..9564cb999da
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/addVal.kt
@@ -0,0 +1,3 @@
+class Foo(x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/addVal.kt.after b/idea/testData/intentions/addValOrVar/addVal.kt.after
new file mode 100644
index 00000000000..693e712d9ee
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/addVal.kt.after
@@ -0,0 +1,3 @@
+class Foo(val x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/funParameter.kt b/idea/testData/intentions/addValOrVar/funParameter.kt
new file mode 100644
index 00000000000..7df2d98fa7d
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/funParameter.kt
@@ -0,0 +1,4 @@
+// IS_APPLICABLE: false
+fun foo(x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/hasVal.kt b/idea/testData/intentions/addValOrVar/hasVal.kt
new file mode 100644
index 00000000000..c6053b0afc0
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/hasVal.kt
@@ -0,0 +1,4 @@
+// IS_APPLICABLE: false
+class Foo(val x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/hasVar.kt b/idea/testData/intentions/addValOrVar/hasVar.kt
new file mode 100644
index 00000000000..8505d727e87
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/hasVar.kt
@@ -0,0 +1,4 @@
+// IS_APPLICABLE: false
+class Foo(var x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/outOfRange.kt b/idea/testData/intentions/addValOrVar/outOfRange.kt
new file mode 100644
index 00000000000..09d01128610
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/outOfRange.kt
@@ -0,0 +1,4 @@
+// IS_APPLICABLE: false
+class Foo(x: Int, y: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/addValOrVar/secondaryConstructorParameter.kt b/idea/testData/intentions/addValOrVar/secondaryConstructorParameter.kt
new file mode 100644
index 00000000000..c2ad4a12c10
--- /dev/null
+++ b/idea/testData/intentions/addValOrVar/secondaryConstructorParameter.kt
@@ -0,0 +1,4 @@
+// IS_APPLICABLE: false
+class Foo {
+ constructor(x: Int, y: Int)
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
index bf7eab21b2a..693d390a789 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -362,6 +362,51 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/addValOrVar")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class AddValOrVar extends AbstractIntentionTest {
+ @TestMetadata("addVal.kt")
+ public void testAddVal() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/addVal.kt");
+ doTest(fileName);
+ }
+
+ public void testAllFilesPresentInAddValOrVar() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/addValOrVar"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
+ }
+
+ @TestMetadata("funParameter.kt")
+ public void testFunParameter() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/funParameter.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("hasVal.kt")
+ public void testHasVal() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/hasVal.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("hasVar.kt")
+ public void testHasVar() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/hasVar.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("outOfRange.kt")
+ public void testOutOfRange() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/outOfRange.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("secondaryConstructorParameter.kt")
+ public void testSecondaryConstructorParameter() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/addValOrVar/secondaryConstructorParameter.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/intentions/anonymousFunctionToLambda")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)