Quick fix for enum entry super constructor syntax fix, together with a set of tests

This commit is contained in:
Mikhail Glukhikh
2015-05-08 18:05:03 +03:00
parent 147bca3d22
commit da3d083dc0
19 changed files with 280 additions and 1 deletions
@@ -261,6 +261,11 @@ public class JetPsiFactory(private val project: Project) {
return createDeclaration<JetClass>("enum class E {$text}").getDeclarations()[0] as JetEnumEntry
}
public fun createEnumEntrySuperclassReferenceExpression(): JetEnumEntrySuperclassReferenceExpression {
val userType = createEnumEntry("Entry()").getInitializerList()!!.getInitializers()[0].getTypeReference()!!.getTypeElement() as JetUserType
return userType.getReferenceExpression() as JetEnumEntrySuperclassReferenceExpression
}
public fun createWhenEntry(entryText: String): JetWhenEntry {
val function = createFunction("fun foo() { when(12) { " + entryText + " } }")
val whenEntry = PsiTreeUtil.findChildOfType(function, javaClass<JetWhenEntry>())
@@ -0,0 +1,68 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.JetNodeTypes
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.lexer.JetTokens
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
import org.jetbrains.kotlin.resolve.DeclarationsChecker
class DeprecatedEnumEntrySuperConstructorSyntaxFix(element: JetEnumEntry): JetIntentionAction<JetEnumEntry>(element) {
override fun getFamilyName(): String = getText()
override fun getText(): String = "Change to short enum entry super constructor"
override fun invoke(project: Project, editor: Editor?, file: JetFile?) = changeConstructorToShort(element)
companion object: JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? =
diagnostic.createIntentionForFirstParentOfType(::DeprecatedEnumEntrySuperConstructorSyntaxFix)
public fun createWholeProjectFixFactory(): JetSingleIntentionActionFactory = createIntentionFactory {
JetWholeProjectForEachElementOfTypeFix.createByPredicate<JetEnumEntry>(
predicate = { DeclarationsChecker.enumEntryUsesDeprecatedSuperConstructor(it) },
taskProcessor = { changeConstructorToShort(it) },
modalTitle = "Replacing deprecated enum constructor syntax",
name = "Change to short enum entry super constructor in the whole project",
familyName = "Change to short enum entry super constructor in the whole project"
)
}
private fun transformInitializerList(list: JetInitializerList) {
val psiFactory = JetPsiFactory(list)
val userType = list.getInitializers()[0].getTypeReference()!!.getTypeElement() as JetUserType
userType.getReferenceExpression()!!.replace(psiFactory.createEnumEntrySuperclassReferenceExpression())
}
private fun changeConstructorToShort(entry: JetEnumEntry) {
val list = entry.getInitializerList()!!
transformInitializerList(list)
// Delete everything between name and initializer (colon with whitespaces)
entry.deleteChildRange(entry.getFirstChild().getNextSibling(), list.getPrevSibling())
}
}
}
@@ -325,5 +325,8 @@ public class QuickFixRegistrar {
QuickFixes.factories.put(DEPRECATED_ANNOTATION_SYNTAX, DeprecatedAnnotationSyntaxFix.Companion);
QuickFixes.factories.put(DEPRECATED_ANNOTATION_SYNTAX, DeprecatedAnnotationSyntaxFix.Companion.createWholeProjectFixFactory());
QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_SUPER_CONSTRUCTOR, DeprecatedEnumEntrySuperConstructorSyntaxFix.Companion);
QuickFixes.factories.put(ENUM_ENTRY_USES_DEPRECATED_SUPER_CONSTRUCTOR, DeprecatedEnumEntrySuperConstructorSyntaxFix.Companion.createWholeProjectFixFactory());
}
}
@@ -3,5 +3,5 @@
// ACTION: Create property 'x'
enum class E(n: Int) {
X: E(<caret>x)
X(<caret>x)
}
@@ -0,0 +1,8 @@
// "Change to short enum entry super constructor" "true"
enum class MyEnum(val z: Int) {
A: MyEnum(3)<caret>
B(7)
C(12)
fun foo() = z * 2
}
@@ -0,0 +1,8 @@
// "Change to short enum entry super constructor" "true"
enum class MyEnum(val z: Int) {
A(3)
B(7)
C(12)
fun foo() = z * 2
}
@@ -0,0 +1,8 @@
// "Change to short enum entry super constructor" "true"
enum class MyEnum(val z: Int) {
A(3)
B(7)
C: MyEnum(12)<caret>
fun foo() = z * 2
}
@@ -0,0 +1,8 @@
// "Change to short enum entry super constructor" "true"
enum class MyEnum(val z: Int) {
A(3)
B(7)
C(12)
fun foo() = z * 2
}
@@ -0,0 +1,5 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String) {
UNIQUE: SimpleEnum("42")<caret>
}
@@ -0,0 +1,5 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String) {
UNIQUE("42")
}
@@ -0,0 +1,24 @@
// "Change to short enum entry super constructor in the whole project" "true"
enum class First(val colorCode: Int) {
RED: First(0xff0000),
GREEN: First(0x00ff00)<caret>, BLUE: First(0x0000ff)
}
enum class Second(val dirCode: Int) {
NORTH: Second(1) {
override fun dir(): String = "N"
},
SOUTH: Second(2) {
override fun dir(): String = "S"
},
WEST : Second(3) {
override fun dir(): String = "W"
},
EAST: Second(4) {
override fun dir(): String = "E"
};
abstract fun dir(): String
}
@@ -0,0 +1,24 @@
// "Change to short enum entry super constructor in the whole project" "true"
enum class First(val colorCode: Int) {
RED(0xff0000),
GREEN(0x00ff00), BLUE(0x0000ff)
}
enum class Second(val dirCode: Int) {
NORTH(1) {
override fun dir(): String = "N"
},
SOUTH(2) {
override fun dir(): String = "S"
},
WEST(3) {
override fun dir(): String = "W"
},
EAST(4) {
override fun dir(): String = "E"
};
abstract fun dir(): String
}
@@ -0,0 +1,9 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST(),
SECOND: SimpleEnum("42")<caret>,
LAST("13");
fun foo() = z
}
@@ -0,0 +1,9 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST(),
SECOND("42"),
LAST("13");
fun foo() = z
}
@@ -0,0 +1,9 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST(),
SECOND: SimpleEnum(z = "42")<caret>,
LAST("13");
fun foo() = z
}
@@ -0,0 +1,9 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST(),
SECOND(z = "42")<caret>,
LAST("13");
fun foo() = z
}
@@ -0,0 +1,13 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST: SimpleEnum()<caret> {
override fun foo(): String = "abc"
},
SECOND() {
override fun foo(): String = "xyz"
},
LAST("13");
open fun foo(): String = z
}
@@ -0,0 +1,13 @@
// "Change to short enum entry super constructor" "true"
enum class SimpleEnum(val z: String = "xxx") {
FIRST() {
override fun foo(): String = "abc"
},
SECOND() {
override fun foo(): String = "xyz"
},
LAST("13");
open fun foo(): String = z
}
@@ -3031,6 +3031,57 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
@TestMetadata("idea/testData/quickfix/migration/enumConstructor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EnumConstructor extends AbstractQuickFixTest {
public void testAllFilesPresentInEnumConstructor() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/enumConstructor"), Pattern.compile("^(\\w+)\\.kt$"), true);
}
@TestMetadata("noDelimiterWithInitializerFirst.kt")
public void testNoDelimiterWithInitializerFirst() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/noDelimiterWithInitializerFirst.kt");
doTest(fileName);
}
@TestMetadata("noDelimiterWithInitializerLast.kt")
public void testNoDelimiterWithInitializerLast() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/noDelimiterWithInitializerLast.kt");
doTest(fileName);
}
@TestMetadata("singleEntry.kt")
public void testSingleEntry() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/singleEntry.kt");
doTest(fileName);
}
@TestMetadata("wholeProject.kt")
public void testWholeProject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/wholeProject.kt");
doTest(fileName);
}
@TestMetadata("withCommas.kt")
public void testWithCommas() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/withCommas.kt");
doTest(fileName);
}
@TestMetadata("withNamedArgument.kt")
public void testWithNamedArgument() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/withNamedArgument.kt");
doTest(fileName);
}
@TestMetadata("withOverloads.kt")
public void testWithOverloads() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/enumConstructor/withOverloads.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/migration/lambdaSyntax")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)