From 2b63bcaa19dd443bfa654956e9de5fc77b217911 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 9 Sep 2016 04:58:15 +0300 Subject: [PATCH] Correct diagnostics and quick-fix for T::class with non-reified type parameter #KT-9590 fixed --- ...ifiedTypeParameterSubstitutionChecker.java | 2 +- .../DoubleColonExpressionResolver.kt | 14 ++-- .../tests/classLiteral/nonClassesOnLHS.kt | 2 +- .../generics/tpAsReified/ClassDereference.kt | 3 + .../generics/tpAsReified/ClassDereference.txt | 3 + .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../AddReifiedToTypeParameterOfFunctionFix.kt | 68 +++++++++++++++++++ .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 2 + .../doubleColonClass.kt | 4 ++ .../doubleColonClass.kt.after | 4 ++ .../secondTypeParameter.kt | 6 ++ .../secondTypeParameter.kt.after | 6 ++ .../toTypedArray.kt | 6 ++ .../toTypedArray.kt.after | 6 ++ .../idea/quickfix/QuickFixTestGenerated.java | 27 ++++++++ 15 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.kt create mode 100644 compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.txt create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/AddReifiedToTypeParameterOfFunctionFix.kt create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt.after create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt.after create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt create mode 100644 idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java index f8e3bbc9723..84f594b84a0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java @@ -50,7 +50,7 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker { if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor && !((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) { - context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, parameter)); + context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, (TypeParameterDescriptor) argumentDeclarationDescriptor)); } else if (TypeUtilsKt.cannotBeReified(argument)) { context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument)); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 8ab28c1ba9c..99eed86833d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -48,12 +48,11 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver import org.jetbrains.kotlin.resolve.source.toSourceElement -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter +import java.lang.UnsupportedOperationException import javax.inject.Inject sealed class DoubleColonLHS(val type: KotlinType) { @@ -119,7 +118,12 @@ class DoubleColonExpressionResolver( reportError = !isAllowedInClassLiteral(type) } - if (type.isMarkedNullable || reportError) { + + val typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) + if (type is SimpleType && !type.isMarkedNullable && typeParameterDescriptor != null && !typeParameterDescriptor.isReified) { + c.trace.report(TYPE_PARAMETER_AS_REIFIED.on(expression, typeParameterDescriptor)) + } + else if (type.isMarkedNullable || reportError) { c.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression)) } } diff --git a/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.kt b/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.kt index e63e376884b..9063b6038c1 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.kt @@ -9,7 +9,7 @@ val l1 = List?::class val l2 = List?::class fun foo() { - val t1 = T::class + val t1 = T::class val t2 = T?::class } diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.kt b/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.kt new file mode 100644 index 00000000000..7edac44f9b4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.kt @@ -0,0 +1,3 @@ + +fun dereferenceClass(): Any = + T::class diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.txt b/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.txt new file mode 100644 index 00000000000..f7daae668b9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.txt @@ -0,0 +1,3 @@ +package + +public fun dereferenceClass(): kotlin.Any diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 5375a7b1072..bf63da39162 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -8339,6 +8339,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("ClassDereference.kt") + public void testClassDereference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/tpAsReified/ClassDereference.kt"); + doTest(fileName); + } + @TestMetadata("Conventions.kt") public void testConventions() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/tpAsReified/Conventions.kt"); diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReifiedToTypeParameterOfFunctionFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReifiedToTypeParameterOfFunctionFix.kt new file mode 100644 index 00000000000..56fb3c33a1b --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReifiedToTypeParameterOfFunctionFix.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2016 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. + */ + +/* + * Copyright 2010-2016 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.diagnostics.Errors +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtTypeParameter +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType + +class AddReifiedToTypeParameterOfFunctionFix( + typeParameter: KtTypeParameter, + val function: KtNamedFunction +) : AddModifierFix(typeParameter, KtTokens.REIFIED_KEYWORD) { + + val inlineFix = AddInlineToFunctionWithReifiedFix(function) + + override fun getText() = "Make ${getElementName(element)} reified and ${getElementName(function)} inline" + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + super.invoke(project, editor, file) + inlineFix.invoke(project, editor, file) + } + + companion object Factory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val element = Errors.TYPE_PARAMETER_AS_REIFIED.cast(diagnostic) + val function = element.psiElement.getStrictParentOfType() + val parameter = function?.typeParameterList?.parameters?.get(element.a.index) ?: return null + return AddReifiedToTypeParameterOfFunctionFix(parameter, function) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 8fd0f302c0a..92cfca9d224 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -418,5 +418,7 @@ class QuickFixRegistrar : QuickFixContributor { UNRESOLVED_REFERENCE.registerFactory(CreateTypeParameterByRefActionFactory) FINAL_UPPER_BOUND.registerFactory(InlineTypeParameterFix) + + TYPE_PARAMETER_AS_REIFIED.registerFactory(AddReifiedToTypeParameterOfFunctionFix) } } diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt new file mode 100644 index 00000000000..e83d5a70004 --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt @@ -0,0 +1,4 @@ +// "Make 'T' reified and 'dereferenceClass' inline" "true" + +fun dereferenceClass(): Any = + T::class diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt.after b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt.after new file mode 100644 index 00000000000..52536badb90 --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt.after @@ -0,0 +1,4 @@ +// "Make 'T' reified and 'dereferenceClass' inline" "true" + +inline fun dereferenceClass(): Any = + T::class diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt new file mode 100644 index 00000000000..4ba67869a00 --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt @@ -0,0 +1,6 @@ +// "Make 'R' reified and 'flatten' inline" "true" +// WITH_RUNTIME + +fun >, R> T.flatten(): Array { + return this.flatMap { it.asIterable() }.toTypedArray() +} \ No newline at end of file diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt.after b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt.after new file mode 100644 index 00000000000..77f162b726a --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt.after @@ -0,0 +1,6 @@ +// "Make 'R' reified and 'flatten' inline" "true" +// WITH_RUNTIME + +inline fun >, reified R> T.flatten(): Array { + return this.flatMap { it.asIterable() }.toTypedArray() +} \ No newline at end of file diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt new file mode 100644 index 00000000000..64e2ac57584 --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt @@ -0,0 +1,6 @@ +// "Make 'T' reified and 'flatten' inline" "true" +// WITH_RUNTIME + +fun Array>.flatten(): Array { + return this.flatMap { it.asIterable() }.toTypedArray() +} \ No newline at end of file diff --git a/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt.after b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt.after new file mode 100644 index 00000000000..3d04ff5ff13 --- /dev/null +++ b/idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt.after @@ -0,0 +1,6 @@ +// "Make 'T' reified and 'flatten' inline" "true" +// WITH_RUNTIME + +inline fun Array>.flatten(): Array { + return this.flatMap { it.asIterable() }.toTypedArray() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 1ce57f508e8..1ad93c32500 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -413,6 +413,33 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddReifiedToTypeParameterOfFunctionFix extends AbstractQuickFixTest { + public void testAllFilesPresentInAddReifiedToTypeParameterOfFunctionFix() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); + } + + @TestMetadata("doubleColonClass.kt") + public void testDoubleColonClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/doubleColonClass.kt"); + doTest(fileName); + } + + @TestMetadata("secondTypeParameter.kt") + public void testSecondTypeParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/secondTypeParameter.kt"); + doTest(fileName); + } + + @TestMetadata("toTypedArray.kt") + public void testToTypedArray() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addReifiedToTypeParameterOfFunctionFix/toTypedArray.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/addRunBeforeLambda") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)