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<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
|
// 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(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}",
|
MAP.put(TYPE_VARIANCE_CONFLICT, "Type parameter {0} is declared as ''{1}'' but occurs in ''{2}'' position in type {3}",
|
||||||
new MultiRenderer<VarianceConflictDiagnosticData>() {
|
new MultiRenderer<VarianceConflictDiagnosticData>() {
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ public class DeclarationsChecker {
|
|||||||
if (!constraints.isEmpty()) {
|
if (!constraints.isEmpty()) {
|
||||||
for (JetTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) {
|
for (JetTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) {
|
||||||
if (typeParameter.getExtendsBound() != null && hasConstraints(typeParameter, constraints)) {
|
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> {
|
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : Cloneable<!>> where T : Comparable<T> {
|
||||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAITS!>U : Cloneable<!>> foo(u: U): U where U: Comparable<U> {
|
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>U : Cloneable<!>> foo(u: U): U where U: Comparable<U> {
|
||||||
return 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 }
|
get() { return null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
|
|||||||
Errors.BACKING_FIELD_SYNTAX_DEPRECATED,
|
Errors.BACKING_FIELD_SYNTAX_DEPRECATED,
|
||||||
Errors.OPERATOR_MODIFIER_REQUIRED,
|
Errors.OPERATOR_MODIFIER_REQUIRED,
|
||||||
Errors.CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS,
|
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 {
|
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)
|
DEPRECATED_TYPE_PARAMETER_SYNTAX.registerFactory(MigrateTypeParameterListFix)
|
||||||
|
|
||||||
UNRESOLVED_REFERENCE.registerFactory(KotlinAddOrderEntryActionFactory)
|
UNRESOLVED_REFERENCE.registerFactory(KotlinAddOrderEntryActionFactory)
|
||||||
|
|
||||||
|
MISPLACED_TYPE_PARAMETER_CONSTRAINTS.registerFactory(MoveTypeParameterConstraintFix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -14,8 +14,9 @@ class D() {
|
|||||||
companion object : A(), B {}
|
companion object : A(), B {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Test1<T : A>()
|
class Test1<T>()
|
||||||
where
|
where
|
||||||
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
<error>B</error> : T // error
|
<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 Buzz<T> where T : <warning>Bar<<error>Int</error>></warning>, T : <error>nioho</error>
|
||||||
|
|
||||||
class X<T : <warning>Foo</warning>>
|
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
|
where
|
||||||
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
<error>B</error> : T
|
<error>B</error> : T
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,3 +63,6 @@ class C {
|
|||||||
|
|
||||||
fun typed<T>() {
|
fun typed<T>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T : Cloneable> withTypeParameters() where T : Comparable<T> {
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,3 +62,6 @@ class C {
|
|||||||
|
|
||||||
fun <T> typed() {
|
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")
|
@TestMetadata("idea/testData/quickfix/typeProjection")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user