quickfix to move type constraint to 'where' clause
This commit is contained in:
@@ -268,7 +268,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<PsiElement> CYCLIC_GENERIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetTypeParameter> MISPLACED_TYPE_PARAMETER_CONSTRAITS = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<JetTypeParameter> MISPLACED_TYPE_PARAMETER_CONSTRAINTS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
// Members
|
||||
|
||||
|
||||
+1
-1
@@ -496,7 +496,7 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(DEPRECATED_TYPE_PARAMETER_SYNTAX, "Placing function type parameters after the function name is deprecated");
|
||||
|
||||
MAP.put(MISPLACED_TYPE_PARAMETER_CONSTRAITS, "If a type parameter has multiple constraints, they all need to be placed in the 'where' clause");
|
||||
MAP.put(MISPLACED_TYPE_PARAMETER_CONSTRAINTS, "If a type parameter has multiple constraints, they all need to be placed in the 'where' clause");
|
||||
|
||||
MAP.put(TYPE_VARIANCE_CONFLICT, "Type parameter {0} is declared as ''{1}'' but occurs in ''{2}'' position in type {3}",
|
||||
new MultiRenderer<VarianceConflictDiagnosticData>() {
|
||||
|
||||
@@ -342,7 +342,7 @@ public class DeclarationsChecker {
|
||||
if (!constraints.isEmpty()) {
|
||||
for (JetTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) {
|
||||
if (typeParameter.getExtendsBound() != null && hasConstraints(typeParameter, constraints)) {
|
||||
trace.report(MISPLACED_TYPE_PARAMETER_CONSTRAITS.on(typeParameter));
|
||||
trace.report(MISPLACED_TYPE_PARAMETER_CONSTRAINTS.on(typeParameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAITS!>T : Cloneable<!>> where T : Comparable<T> {
|
||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAITS!>U : Cloneable<!>> foo(u: U): U where U: Comparable<U> {
|
||||
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : Cloneable<!>> where T : Comparable<T> {
|
||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>U : Cloneable<!>> foo(u: U): U where U: Comparable<U> {
|
||||
return u
|
||||
}
|
||||
|
||||
val <<!MISPLACED_TYPE_PARAMETER_CONSTRAITS!>U : Cloneable<!>> U.foo: U? where U: Comparable<U>
|
||||
val <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>U : Cloneable<!>> U.foo: U? where U: Comparable<U>
|
||||
get() { return null }
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
|
||||
Errors.BACKING_FIELD_SYNTAX_DEPRECATED,
|
||||
Errors.OPERATOR_MODIFIER_REQUIRED,
|
||||
Errors.CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS,
|
||||
Errors.DEPRECATED_TYPE_PARAMETER_SYNTAX
|
||||
Errors.DEPRECATED_TYPE_PARAMETER_SYNTAX,
|
||||
Errors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
|
||||
)
|
||||
|
||||
private fun Diagnostic.isObsoleteLabel(): Boolean {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
|
||||
class MoveTypeParameterConstraintFix(element: JetTypeParameter) : JetIntentionAction<JetTypeParameter>(element), CleanupFix {
|
||||
override fun getText(): String = "Move type parameter constraint to 'where' clause"
|
||||
override fun getFamilyName(): String = text
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||
val typeParameterName = element.nameAsName ?: return
|
||||
val psiFactory = JetPsiFactory(file)
|
||||
val templateClass = psiFactory.buildDeclaration {
|
||||
appendFixedText("class A<")
|
||||
appendName(typeParameterName)
|
||||
appendFixedText("> where ")
|
||||
appendName(typeParameterName)
|
||||
appendFixedText(":")
|
||||
appendTypeReference(element.extendsBound)
|
||||
} as JetTypeParameterListOwner
|
||||
val templateConstraintList = templateClass.typeConstraintList!!
|
||||
|
||||
val declaration = element.getStrictParentOfType<JetTypeParameterListOwner>() ?: return
|
||||
val constraintList = declaration.typeConstraintList ?: return
|
||||
constraintList.addAfter(psiFactory.createComma(), null)
|
||||
constraintList.addAfter(templateConstraintList.constraints[0], null)
|
||||
|
||||
element.extendsBound?.delete()
|
||||
val colon = element.node.findChildByType(JetTokens.COLON)
|
||||
colon?.psi?.delete()
|
||||
}
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val typeParameter = diagnostic.psiElement as? JetTypeParameter ?: return null
|
||||
return MoveTypeParameterConstraintFix(typeParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,5 +340,7 @@ public class QuickFixRegistrar : QuickFixContributor {
|
||||
DEPRECATED_TYPE_PARAMETER_SYNTAX.registerFactory(MigrateTypeParameterListFix)
|
||||
|
||||
UNRESOLVED_REFERENCE.registerFactory(KotlinAddOrderEntryActionFactory)
|
||||
|
||||
MISPLACED_TYPE_PARAMETER_CONSTRAINTS.registerFactory(MoveTypeParameterConstraintFix)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -14,8 +14,9 @@ class D() {
|
||||
companion object : A(), B {}
|
||||
}
|
||||
|
||||
class Test1<T : A>()
|
||||
class Test1<T>()
|
||||
where
|
||||
T : A,
|
||||
T : B,
|
||||
<error>B</error> : T // error
|
||||
{
|
||||
@@ -41,10 +42,11 @@ class Bar<T : <warning>Foo</warning>>
|
||||
class Buzz<T> where T : <warning>Bar<<error>Int</error>></warning>, T : <error>nioho</error>
|
||||
|
||||
class X<T : <warning>Foo</warning>>
|
||||
class Y<<error>T</error> : <warning>Foo</warning>> where T : <warning>Bar<Foo></warning>
|
||||
class Y<<error>T</error>> where T : <warning>Foo</warning>, T : <warning>Bar<Foo></warning>
|
||||
|
||||
fun <T : A> test2(t : T)
|
||||
fun <T> test2(t : T)
|
||||
where
|
||||
T : A,
|
||||
T : B,
|
||||
<error>B</error> : T
|
||||
{
|
||||
|
||||
@@ -63,3 +63,6 @@ class C {
|
||||
|
||||
fun typed<T>() {
|
||||
}
|
||||
|
||||
fun <T : Cloneable> withTypeParameters() where T : Comparable<T> {
|
||||
}
|
||||
|
||||
@@ -62,3 +62,6 @@ class C {
|
||||
|
||||
fun <T> typed() {
|
||||
}
|
||||
|
||||
fun <T> withTypeParameters() where T : Cloneable, T : Comparable<T> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Move type parameter constraint to 'where' clause" "true"
|
||||
class A<<caret>T : Cloneable> where T : Comparable<*> {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Move type parameter constraint to 'where' clause" "true"
|
||||
class A<T> where T : Cloneable, T : Comparable<*> {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Move type parameter constraint to 'where' clause" "true"
|
||||
fun <<caret>T : Cloneable> foo() where T : Comparable<*> {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Move type parameter constraint to 'where' clause" "true"
|
||||
fun <T> foo() where T : Cloneable, T : Comparable<*> {
|
||||
}
|
||||
@@ -6544,6 +6544,27 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/typeParameters")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class TypeParameters extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInTypeParameters() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/typeParameters"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("misplacedClassTypeParameter.kt")
|
||||
public void testMisplacedClassTypeParameter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeParameters/misplacedClassTypeParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("misplacedFunctionTypeParameter.kt")
|
||||
public void testMisplacedFunctionTypeParameter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/typeParameters/misplacedFunctionTypeParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/typeProjection")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user