Introduce "Add missing 'class' keyword" intention

#KT-14884 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-11-01 02:54:29 +01:00
committed by Vladimir Dolzhenko
parent 9634e6fba3
commit b4c62cdb52
21 changed files with 164 additions and 1 deletions
@@ -1644,6 +1644,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.AddMissingClassKeywordIntention</className>
<category>Kotlin</category>
</intentionAction>
<lang.inspectionSuppressor language="kotlin" implementationClass="org.jetbrains.kotlin.idea.inspections.KotlinInspectionSuppressor"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection"
@@ -0,0 +1 @@
enum <spot>class</spot> E
@@ -0,0 +1,5 @@
<html>
<body>
This intention adds a missing <b>class</b> keyword.
</body>
</html>
@@ -2195,5 +2195,5 @@ move.refactoring.error.text.cannot.perform.refactoring.since.the.following.files
kotlin.script.definitions.model.name.is.enabled=Is Enabled
kotlin.script.definitions.model.name.pattern.extension=Pattern/Extension
kotlin.script.definitions.model.name.name=Name
codestyle.name.kotlin=Kotlin
add.missing.class.keyword=Add missing 'class' keyword
fix.move.typealias.to.top.level=Move typealias to top level
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.startOffset
class AddMissingClassKeywordIntention : SelfTargetingIntention<PsiElement>(
PsiElement::class.java,
KotlinBundle.message("add.missing.class.keyword")
) {
companion object {
private val targetKeywords = listOf(
KtTokens.ANNOTATION_KEYWORD,
KtTokens.DATA_KEYWORD,
KtTokens.SEALED_KEYWORD,
KtTokens.INNER_KEYWORD
)
}
override fun isApplicableTo(element: PsiElement, caretOffset: Int): Boolean {
if (element.node?.elementType != KtTokens.IDENTIFIER) return false
val ktClass = element.parent as? KtClass
if (ktClass == null) {
val errorElement = element.parent as? PsiErrorElement ?: return false
val modifierList = errorElement.getPrevSiblingIgnoringWhitespaceAndComments() as? KtModifierList ?: return false
return targetKeywords.any { modifierList.hasModifier(it) }
} else {
return ktClass.isEnum() && ktClass.getClassKeyword() == null
}
}
override fun applyTo(element: PsiElement, editor: Editor?) {
val document = editor?.document ?: return
val targetElement = (element.parent as? PsiErrorElement) ?: element
document.insertString(targetElement.startOffset, "class ")
PsiDocumentManager.getInstance(element.project).commitDocument(document)
}
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.intentions.AddMissingClassKeywordIntention
@@ -0,0 +1,5 @@
// IS_APPLICABLE: false
// DISABLE-ERRORS
abstract <caret>Foo {
abstract fun foo()
}
@@ -0,0 +1 @@
annotation <caret>Foo
@@ -0,0 +1 @@
annotation class Foo
@@ -0,0 +1,7 @@
// DISABLE-ERRORS
annotation class Ann
@Ann
private data <caret>Foo(val s: String) {
fun foo() {}
}
@@ -0,0 +1,7 @@
// DISABLE-ERRORS
annotation class Ann
@Ann
private data class Foo(val s: String) {
fun foo() {}
}
@@ -0,0 +1,2 @@
// IS_APPLICABLE: false
private data class <caret>Foo(val s: String)
@@ -0,0 +1,3 @@
enum Foo<caret>(val s: String) {
A("a"), B("b")
}
@@ -0,0 +1,3 @@
enum class Foo(val s: String) {
A("a"), B("b")
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
enum class <caret>Foo(val s: String) {
A("a"), B("b")
}
@@ -0,0 +1,3 @@
class C {
inner <caret>Foo
}
@@ -0,0 +1,3 @@
class C {
inner class Foo
}
@@ -0,0 +1,4 @@
// DISABLE-ERRORS
sealed <caret>Foo {
abstract fun foo()
}
@@ -0,0 +1,4 @@
// DISABLE-ERRORS
sealed class Foo {
abstract fun foo()
}
@@ -1130,6 +1130,59 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
@TestMetadata("idea/testData/intentions/addMissingClassKeyword")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddMissingClassKeyword extends AbstractIntentionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("abstract.kt")
public void testAbstract() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/abstract.kt");
}
public void testAllFilesPresentInAddMissingClassKeyword() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/addMissingClassKeyword"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), true);
}
@TestMetadata("annottion.kt")
public void testAnnottion() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/annottion.kt");
}
@TestMetadata("data.kt")
public void testData() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/data.kt");
}
@TestMetadata("dataHasClassKeyword.kt")
public void testDataHasClassKeyword() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/dataHasClassKeyword.kt");
}
@TestMetadata("enum.kt")
public void testEnum() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/enum.kt");
}
@TestMetadata("enumHasClassKeyword.kt")
public void testEnumHasClassKeyword() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/enumHasClassKeyword.kt");
}
@TestMetadata("inner.kt")
public void testInner() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/inner.kt");
}
@TestMetadata("sealed.kt")
public void testSealed() throws Exception {
runTest("idea/testData/intentions/addMissingClassKeyword/sealed.kt");
}
}
@TestMetadata("idea/testData/intentions/addMissingDestructuring")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)