Prohibit type parameters for local variables in LV >= 1.4 & -progressive

#KT-8341 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-12-24 01:30:17 +03:00
parent e509649132
commit 958aeff94b
18 changed files with 172 additions and 2 deletions
@@ -954,6 +954,8 @@ public interface Errors {
DiagnosticFactory0<KtTypeReference> LOCAL_EXTENSION_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_GETTER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyAccessor> LOCAL_VARIABLE_WITH_SETTER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory3<KtExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
@@ -399,6 +399,8 @@ public class DefaultErrorMessages {
MAP.put(LOCAL_EXTENSION_PROPERTY, "Local extension properties are not allowed");
MAP.put(LOCAL_VARIABLE_WITH_GETTER, "Local variables are not allowed to have getters");
MAP.put(LOCAL_VARIABLE_WITH_SETTER, "Local variables are not allowed to have setters");
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated");
MAP.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters");
MAP.put(VAL_WITH_SETTER, "A 'val'-property cannot have a setter");
MAP.put(DEPRECATED_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is deprecated", RENDER_TYPE, RENDER_TYPE);
@@ -33,7 +33,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
PropertiesWithBackingFieldsInsideInlineClass(),
AnnotationClassTargetAndRetentionChecker(),
ReservedMembersAndConstructsForInlineClass(),
ResultClassInReturnTypeChecker()
ResultClassInReturnTypeChecker(),
LocalVariableTypeParametersChecker()
)
private val DEFAULT_CALL_CHECKERS = listOf(
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.resolve.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
class LocalVariableTypeParametersChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtProperty || descriptor !is LocalVariableDescriptor) return
val typeParameters = declaration.typeParameters
val typeParametersList = declaration.typeParameterList
if (typeParameters.isEmpty() || typeParametersList == null) return
val diagnostic =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitTypeParametersForLocalVariables))
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS
else
Errors.LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING
context.trace.report(diagnostic.on(typeParametersList))
}
}
@@ -7,6 +7,6 @@ class SomeClass {
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> T.field: Int get() = 12
fun foo() {
val <<!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>(3)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!>(12)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>("Test")<!> T> <!UNUSED_VARIABLE!>localVal<!> = 12
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><<!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>(3)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!>(12)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>("Test")<!> T><!> <!UNUSED_VARIABLE!>localVal<!> = 12
}
}
@@ -0,0 +1,19 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !LANGUAGE: -ProhibitTypeParametersForLocalVariables
import kotlin.reflect.KProperty
fun test() {
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a0 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T : <!DEBUG_INFO_MISSING_UNRESOLVED!>__UNRESOLVED__<!>><!> a1 = ""
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T : <!DEBUG_INFO_MISSING_UNRESOLVED!>String<!>><!> a2 = 0
<!WRONG_MODIFIER_TARGET!>const<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a4 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a5 by Delegate<Int>()
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
}
class Delegate<F> {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ""
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {}
}
@@ -0,0 +1,12 @@
package
public fun test(): kotlin.Unit
public final class Delegate</*0*/ F> {
public constructor Delegate</*0*/ F>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,19 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !LANGUAGE: +ProhibitTypeParametersForLocalVariables
import kotlin.reflect.KProperty
fun test() {
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a0 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T : <!DEBUG_INFO_MISSING_UNRESOLVED!>__UNRESOLVED__<!>><!> a1 = ""
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T : <!DEBUG_INFO_MISSING_UNRESOLVED!>String<!>><!> a2 = 0
<!WRONG_MODIFIER_TARGET!>const<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a4 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a5 by Delegate<Int>()
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
}
class Delegate<F> {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ""
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {}
}
@@ -0,0 +1,12 @@
package
public fun test(): kotlin.Unit
public final class Delegate</*0*/ F> {
public constructor Delegate</*0*/ F>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -5133,6 +5133,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/declarationChecks/LocalVariableWithNoTypeInformation.kt");
}
@TestMetadata("localVariablesWithTypeParameters_1_3.kt")
public void testLocalVariablesWithTypeParameters_1_3() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_3.kt");
}
@TestMetadata("localVariablesWithTypeParameters_1_4.kt")
public void testLocalVariablesWithTypeParameters_1_4() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt");
}
@TestMetadata("mulitpleVarargParameters.kt")
public void testMulitpleVarargParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/mulitpleVarargParameters.kt");
@@ -5133,6 +5133,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/declarationChecks/LocalVariableWithNoTypeInformation.kt");
}
@TestMetadata("localVariablesWithTypeParameters_1_3.kt")
public void testLocalVariablesWithTypeParameters_1_3() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_3.kt");
}
@TestMetadata("localVariablesWithTypeParameters_1_4.kt")
public void testLocalVariablesWithTypeParameters_1_4() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/localVariablesWithTypeParameters_1_4.kt");
}
@TestMetadata("mulitpleVarargParameters.kt")
public void testMulitpleVarargParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/declarationChecks/mulitpleVarargParameters.kt");
@@ -94,6 +94,7 @@ enum class LanguageFeature(
WarningOnMainUnusedParameter(KOTLIN_1_4),
PolymorphicSignature(KOTLIN_1_4),
ProhibitConcurrentHashMapContains(KOTLIN_1_4, kind = BUG_FIX),
ProhibitTypeParametersForLocalVariables(KOTLIN_1_4, kind = BUG_FIX),
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
// Temporarily disabled, see KT-27084/KT-22379
@@ -271,6 +271,9 @@ class QuickFixRegistrar : QuickFixContributor {
TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.registerFactory(RemovePsiElementSimpleFix.RemoveTypeArgumentsFactory)
LOCAL_VARIABLE_WITH_TYPE_PARAMETERS.registerFactory(RemovePsiElementSimpleFix.RemoveTypeParametersFactory)
LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING.registerFactory(RemovePsiElementSimpleFix.RemoveTypeParametersFactory)
UNCHECKED_CAST.registerFactory(ChangeToStarProjectionFix)
CANNOT_CHECK_FOR_ERASED.registerFactory(ChangeToStarProjectionFix)
@@ -58,6 +58,13 @@ open class RemovePsiElementSimpleFix(element: PsiElement, private val text: Stri
}
}
object RemoveTypeParametersFactory : KotlinSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<PsiElement>? {
val element = diagnostic.psiElement.getNonStrictParentOfType<KtTypeParameterList>() ?: return null
return RemovePsiElementSimpleFix(element, "Remove type parameters")
}
}
object RemoveVariableFactory : KotlinSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<PsiElement>? {
val expression = diagnostic.psiElement.getNonStrictParentOfType<KtProperty>() ?: return null
@@ -0,0 +1,5 @@
// "Remove type parameters" "true"
fun test() {
val <caret><T : unresovled_reference, K> x = 0
}
@@ -0,0 +1,5 @@
// "Remove type parameters" "true"
fun test() {
val x = 0
}
@@ -2840,6 +2840,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
}
@TestMetadata("idea/testData/quickfix/localVariableWithTypeParameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalVariableWithTypeParameters extends AbstractQuickFixMultiFileTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTestWithExtraFile, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInLocalVariableWithTypeParameters() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/localVariableWithTypeParameters"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true);
}
}
@TestMetadata("idea/testData/quickfix/makeConstructorParameterProperty")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -7415,6 +7415,24 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
@TestMetadata("idea/testData/quickfix/localVariableWithTypeParameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LocalVariableWithTypeParameters extends AbstractQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInLocalVariableWithTypeParameters() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/localVariableWithTypeParameters"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("removeTypeParametersFromLocalVariable.kt")
public void testRemoveTypeParametersFromLocalVariable() throws Exception {
runTest("idea/testData/quickfix/localVariableWithTypeParameters/removeTypeParametersFromLocalVariable.kt");
}
}
@TestMetadata("idea/testData/quickfix/makeConstructorParameterProperty")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)