Add quickfix for missing 'constructor' inside primary ctor
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||
@@ -85,6 +86,11 @@ public class JetPrimaryConstructor extends JetDeclarationStub<KotlinPlaceHolderS
|
||||
|
||||
public boolean hasConstructorKeyword() {
|
||||
if (getStub() != null) return true;
|
||||
return findChildByType(JetTokens.CONSTRUCTOR_KEYWORD) != null;
|
||||
return getConstructorKeyword() != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getConstructorKeyword() {
|
||||
return findChildByType(JetTokens.CONSTRUCTOR_KEYWORD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +324,9 @@ public class JetPsiFactory(private val project: Project) {
|
||||
return createClass("class A()").getPrimaryConstructor()!!
|
||||
}
|
||||
|
||||
public fun createConstructorKeyword(): PsiElement =
|
||||
createClass("class A constructor()").getPrimaryConstructor()!!.getConstructorKeyword()!!
|
||||
|
||||
public fun createClassLabel(labelName: String): JetSimpleNameExpression {
|
||||
return (createExpression("this@" + labelName) as JetThisExpression).getTargetLabel()!!
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.quickfix
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.addConstructorKeyword
|
||||
|
||||
public class MissingConstructorKeywordFix(element: JetPrimaryConstructor) : JetIntentionAction<JetPrimaryConstructor>(element) {
|
||||
override fun getFamilyName(): String = getText()
|
||||
override fun getText(): String = "Add 'constructor' keyword"
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile?) {
|
||||
element.addConstructorKeyword()
|
||||
}
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? =
|
||||
diagnostic.createIntentionForFirstParentOfType(::MissingConstructorKeywordFix)
|
||||
|
||||
public fun createWholeProjectFixFactory(): JetSingleIntentionActionFactory = createIntentionFactory {
|
||||
JetWholeProjectForEachElementOfTypeFix.createByPredicate<JetPrimaryConstructor>(
|
||||
predicate = { it.getModifierList() != null && !it.hasConstructorKeyword() },
|
||||
taskProcessor = { it.addConstructorKeyword() },
|
||||
modalTitle = "Adding missing 'constructor' keyword",
|
||||
name = "Add missing 'constructor' keyword in whole project",
|
||||
familyName = "Add missing 'constructor' keyword in whole project"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,5 +334,8 @@ public class QuickFixRegistrar {
|
||||
|
||||
QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER, DeprecatedEnumEntryDelimiterSyntaxFix.Companion);
|
||||
QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER, DeprecatedEnumEntryDelimiterSyntaxFix.Companion.createWholeProjectFixFactory());
|
||||
|
||||
QuickFixes.factories.put(MISSING_CONSTRUCTOR_KEYWORD, MissingConstructorKeywordFix.Companion);
|
||||
QuickFixes.factories.put(MISSING_CONSTRUCTOR_KEYWORD, MissingConstructorKeywordFix.Companion.createWholeProjectFixFactory());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.psi.JetPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
inline fun <reified T : PsiElement> Diagnostic.createIntentionForFirstParentOfType(
|
||||
@@ -33,3 +35,8 @@ fun createIntentionFactory(
|
||||
) = object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic) = factory(diagnostic)
|
||||
}
|
||||
|
||||
public fun JetPrimaryConstructor.addConstructorKeyword(): PsiElement? {
|
||||
val keyword = JetPsiFactory(this).createConstructorKeyword()
|
||||
return addAfter(keyword, getModifierList() ?: return null)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Add 'constructor' keyword" "true"
|
||||
|
||||
class A private<caret>()
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Add 'constructor' keyword" "true"
|
||||
|
||||
class A private constructor()
|
||||
+1
@@ -0,0 +1 @@
|
||||
class Q private constructor()
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Add missing 'constructor' keyword in whole project" "true"
|
||||
|
||||
annotation class Ann(val x: Int = 1)
|
||||
|
||||
class A @Ann(1)private constructor(x: Int) {
|
||||
inner class B() // do not insert here
|
||||
inner class C protected constructor() {
|
||||
fun foo() {
|
||||
@data class Local private constructor()
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Add missing 'constructor' keyword in whole project" "true"
|
||||
|
||||
annotation class Ann(val x: Int = 1)
|
||||
|
||||
class A @Ann(1)<caret>private (x: Int) {
|
||||
inner class B() // do not insert here
|
||||
inner class C protected () {
|
||||
fun foo() {
|
||||
@data class Local private()
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
class Q private()
|
||||
@@ -903,6 +903,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/migration/missingConstructorKeyword")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MissingConstructorKeyword extends AbstractQuickFixMultiFileTest {
|
||||
public void testAllFilesPresentInMissingConstructorKeyword() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/missingConstructorKeyword"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("manyFilesMuitliple.before.Main.kt")
|
||||
public void testManyFilesMuitliple() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/missingConstructorKeyword/manyFilesMuitliple.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/migration/replaceJavaClassAsAnnotationParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -3280,6 +3280,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/migration/missingConstructorKeyword")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MissingConstructorKeyword extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInMissingConstructorKeyword() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/missingConstructorKeyword"), Pattern.compile("^(\\w+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("basic.kt")
|
||||
public void testBasic() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/missingConstructorKeyword/basic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/migration/replaceJavaClassAsAnnotationParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user