From 09dc207052a8b84cf99120c18a88e160c2a074f0 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 24 Oct 2016 11:40:01 +0300 Subject: [PATCH] Add SingleUnderscoreForParameterName language feature --- .../kotlin/resolve/ModifiersChecker.java | 2 +- .../resolve/checkers/UnderscoreChecker.kt | 38 ++++++++++++++----- .../BasicExpressionTypingVisitor.java | 2 +- .../expressions/FunctionsTypingVisitor.kt | 2 +- .../tests/SingleUnderscoreUnsupported.kt | 27 +++++++++++++ .../tests/SingleUnderscoreUnsupported.txt | 15 ++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 8 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.kt create mode 100644 compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index 74ce75971cb..ee7f3d34909 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -206,7 +206,7 @@ public class ModifiersChecker { for (KtDestructuringDeclarationEntry multiEntry: multiDeclaration.getEntries()) { annotationChecker.check(multiEntry, trace, null); ModifierCheckerCore.INSTANCE.check(multiEntry, trace, null, languageVersionSettings); - UnderscoreChecker.INSTANCE.checkNamed(multiEntry, trace, /* allowSingleUnderscore = */ true); + UnderscoreChecker.INSTANCE.checkNamed(multiEntry, trace, languageVersionSettings, /* allowSingleUnderscore = */ true); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt index 5e946b16e40..0fa7fb7416b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt @@ -17,6 +17,8 @@ package org.jetbrains.kotlin.resolve.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor @@ -25,39 +27,57 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext -object UnderscoreChecker : SimpleDeclarationChecker { +object UnderscoreChecker : DeclarationChecker { @JvmOverloads - fun checkIdentifier(identifier: PsiElement?, diagnosticHolder: DiagnosticSink, allowSingleUnderscore: Boolean = false) { + fun checkIdentifier( + identifier: PsiElement?, + diagnosticHolder: DiagnosticSink, + languageVersionSettings: LanguageVersionSettings, + allowSingleUnderscore: Boolean = false + ) { if (identifier == null || identifier.text.isEmpty()) return - if (identifier.text.all { it == '_' } && (!allowSingleUnderscore || identifier.text.length != 1)) { + val isValidSingleUnderscore = allowSingleUnderscore && identifier.text == "_" + if (!isValidSingleUnderscore && identifier.text.all { it == '_' }) { diagnosticHolder.report(Errors.UNDERSCORE_IS_RESERVED.on(identifier)) } + else if (isValidSingleUnderscore && !languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) { + diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName)) + } } @JvmOverloads - fun checkNamed(declaration: KtNamedDeclaration, diagnosticHolder: DiagnosticSink, allowSingleUnderscore: Boolean = false) { - checkIdentifier(declaration.nameIdentifier, diagnosticHolder, allowSingleUnderscore) + fun checkNamed( + declaration: KtNamedDeclaration, + diagnosticHolder: DiagnosticSink, + languageVersionSettings: LanguageVersionSettings, + allowSingleUnderscore: Boolean = false + ) { + checkIdentifier(declaration.nameIdentifier, diagnosticHolder, languageVersionSettings, allowSingleUnderscore) } override fun check( declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, - bindingContext: BindingContext + bindingContext: BindingContext, + languageVersionSettings: LanguageVersionSettings ) { if (declaration is KtProperty && descriptor !is VariableDescriptor) return if (declaration is KtCallableDeclaration) { for (parameter in declaration.valueParameters) { - checkNamed(parameter, diagnosticHolder, allowSingleUnderscore = descriptor is FunctionExpressionDescriptor) + checkNamed( + parameter, diagnosticHolder, languageVersionSettings, + allowSingleUnderscore = descriptor is FunctionExpressionDescriptor + ) } } if (declaration is KtTypeParameterListOwner) { for (typeParameter in declaration.typeParameters) { - checkNamed(typeParameter, diagnosticHolder) + checkNamed(typeParameter, diagnosticHolder, languageVersionSettings) } } if (declaration !is KtNamedDeclaration) return - checkNamed(declaration, diagnosticHolder) + checkNamed(declaration, diagnosticHolder, languageVersionSettings) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 723cc63e39c..37429a2d3e2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -870,7 +870,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { KtSimpleNameExpression labelExpression = expression.getTargetLabel(); if (labelExpression != null) { PsiElement labelIdentifier = labelExpression.getIdentifier(); - UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace); + UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace, components.languageVersionSettings); } KtExpression baseExpression = expression.getBaseExpression(); if (baseExpression == null) return TypeInfoFactoryKt.noTypeInfo(context); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index 3b2ed6cab79..2e6921e2636 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -146,7 +146,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre val functionDescriptor = createFunctionLiteralDescriptor(expression, context) expression.valueParameters.forEach { components.identifierChecker.checkDeclaration(it, context.trace) - UnderscoreChecker.checkNamed(it, context.trace, allowSingleUnderscore = true) + UnderscoreChecker.checkNamed(it, context.trace, components.languageVersionSettings, allowSingleUnderscore = true) } val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected) functionDescriptor.setReturnType(safeReturnType) diff --git a/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.kt b/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.kt new file mode 100644 index 00000000000..cb316cf88b2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.kt @@ -0,0 +1,27 @@ +// !LANGUAGE: -SingleUnderscoreForParameterName + +data class A(val x: Int, val y: Int) + +fun foo(a: Array) { + val (_, y) = A(1, 2) + y.hashCode() + + val q1: (Int, String) -> Unit = { + _, s -> s.hashCode() + } + q1(1, "") + + val q2: (Int, String) -> Unit = fun(_: Int, s: String) { + s.hashCode() + } + q2(1, "") + + val q3: (A) -> Unit = { + (_, y) -> y.hashCode() + } + q3(A(2, 3)) + + for ((_, z) in a) { + z.hashCode() + } +} diff --git a/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.txt b/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.txt new file mode 100644 index 00000000000..98548b36ce7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.txt @@ -0,0 +1,15 @@ +package + +public fun foo(/*0*/ a: kotlin.Array): kotlin.Unit + +public final data class A { + public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) + public final val x: kotlin.Int + public final val y: kotlin.Int + public final operator /*synthesized*/ fun component1(): kotlin.Int + public final operator /*synthesized*/ fun component2(): kotlin.Int + public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ...): A + public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 39bb3516f93..b917daf5f81 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -655,6 +655,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("SingleUnderscoreUnsupported.kt") + public void testSingleUnderscoreUnsupported() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/SingleUnderscoreUnsupported.kt"); + doTest(fileName); + } + @TestMetadata("StarsInFunctionCalls.kt") public void testStarsInFunctionCalls() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/StarsInFunctionCalls.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 2c25fcccefd..c561cf6acf6 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -29,6 +29,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion) { DataClassInheritance(KOTLIN_1_1), InlineProperties(KOTLIN_1_1), DestructuringLambdaParameters(KOTLIN_1_1), + SingleUnderscoreForParameterName(KOTLIN_1_1) ; val presentableText: String