Add SingleUnderscoreForParameterName language feature
This commit is contained in:
@@ -206,7 +206,7 @@ public class ModifiersChecker {
|
|||||||
for (KtDestructuringDeclarationEntry multiEntry: multiDeclaration.getEntries()) {
|
for (KtDestructuringDeclarationEntry multiEntry: multiDeclaration.getEntries()) {
|
||||||
annotationChecker.check(multiEntry, trace, null);
|
annotationChecker.check(multiEntry, trace, null);
|
||||||
ModifierCheckerCore.INSTANCE.check(multiEntry, trace, null, languageVersionSettings);
|
ModifierCheckerCore.INSTANCE.check(multiEntry, trace, null, languageVersionSettings);
|
||||||
UnderscoreChecker.INSTANCE.checkNamed(multiEntry, trace, /* allowSingleUnderscore = */ true);
|
UnderscoreChecker.INSTANCE.checkNamed(multiEntry, trace, languageVersionSettings, /* allowSingleUnderscore = */ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.resolve.checkers
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
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.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
|
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.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
object UnderscoreChecker : SimpleDeclarationChecker {
|
object UnderscoreChecker : DeclarationChecker {
|
||||||
|
|
||||||
@JvmOverloads
|
@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 == 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))
|
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
|
@JvmOverloads
|
||||||
fun checkNamed(declaration: KtNamedDeclaration, diagnosticHolder: DiagnosticSink, allowSingleUnderscore: Boolean = false) {
|
fun checkNamed(
|
||||||
checkIdentifier(declaration.nameIdentifier, diagnosticHolder, allowSingleUnderscore)
|
declaration: KtNamedDeclaration,
|
||||||
|
diagnosticHolder: DiagnosticSink,
|
||||||
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
allowSingleUnderscore: Boolean = false
|
||||||
|
) {
|
||||||
|
checkIdentifier(declaration.nameIdentifier, diagnosticHolder, languageVersionSettings, allowSingleUnderscore)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun check(
|
override fun check(
|
||||||
declaration: KtDeclaration,
|
declaration: KtDeclaration,
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptor,
|
||||||
diagnosticHolder: DiagnosticSink,
|
diagnosticHolder: DiagnosticSink,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
) {
|
) {
|
||||||
if (declaration is KtProperty && descriptor !is VariableDescriptor) return
|
if (declaration is KtProperty && descriptor !is VariableDescriptor) return
|
||||||
if (declaration is KtCallableDeclaration) {
|
if (declaration is KtCallableDeclaration) {
|
||||||
for (parameter in declaration.valueParameters) {
|
for (parameter in declaration.valueParameters) {
|
||||||
checkNamed(parameter, diagnosticHolder, allowSingleUnderscore = descriptor is FunctionExpressionDescriptor)
|
checkNamed(
|
||||||
|
parameter, diagnosticHolder, languageVersionSettings,
|
||||||
|
allowSingleUnderscore = descriptor is FunctionExpressionDescriptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (declaration is KtTypeParameterListOwner) {
|
if (declaration is KtTypeParameterListOwner) {
|
||||||
for (typeParameter in declaration.typeParameters) {
|
for (typeParameter in declaration.typeParameters) {
|
||||||
checkNamed(typeParameter, diagnosticHolder)
|
checkNamed(typeParameter, diagnosticHolder, languageVersionSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (declaration !is KtNamedDeclaration) return
|
if (declaration !is KtNamedDeclaration) return
|
||||||
checkNamed(declaration, diagnosticHolder)
|
checkNamed(declaration, diagnosticHolder, languageVersionSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -870,7 +870,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
||||||
if (labelExpression != null) {
|
if (labelExpression != null) {
|
||||||
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
||||||
UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace);
|
UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace, components.languageVersionSettings);
|
||||||
}
|
}
|
||||||
KtExpression baseExpression = expression.getBaseExpression();
|
KtExpression baseExpression = expression.getBaseExpression();
|
||||||
if (baseExpression == null) return TypeInfoFactoryKt.noTypeInfo(context);
|
if (baseExpression == null) return TypeInfoFactoryKt.noTypeInfo(context);
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
|
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
|
||||||
expression.valueParameters.forEach {
|
expression.valueParameters.forEach {
|
||||||
components.identifierChecker.checkDeclaration(it, context.trace)
|
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)
|
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
|
||||||
functionDescriptor.setReturnType(safeReturnType)
|
functionDescriptor.setReturnType(safeReturnType)
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// !LANGUAGE: -SingleUnderscoreForParameterName
|
||||||
|
|
||||||
|
data class A(val x: Int, val y: Int)
|
||||||
|
|
||||||
|
fun foo(a: Array<A>) {
|
||||||
|
val (<!UNSUPPORTED_FEATURE!>_<!>, y) = A(1, 2)
|
||||||
|
y.hashCode()
|
||||||
|
|
||||||
|
val q1: (Int, String) -> Unit = {
|
||||||
|
<!UNSUPPORTED_FEATURE!>_<!>, s -> s.hashCode()
|
||||||
|
}
|
||||||
|
q1(1, "")
|
||||||
|
|
||||||
|
val q2: (Int, String) -> Unit = fun(<!UNSUPPORTED_FEATURE!>_<!>: Int, s: String) {
|
||||||
|
s.hashCode()
|
||||||
|
}
|
||||||
|
q2(1, "")
|
||||||
|
|
||||||
|
val q3: (A) -> Unit = {
|
||||||
|
(<!UNSUPPORTED_FEATURE!>_<!>, y) -> y.hashCode()
|
||||||
|
}
|
||||||
|
q3(A(2, 3))
|
||||||
|
|
||||||
|
for ((<!UNSUPPORTED_FEATURE!>_<!>, z) in a) {
|
||||||
|
z.hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ a: kotlin.Array<A>): 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
|
||||||
|
}
|
||||||
@@ -655,6 +655,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("StarsInFunctionCalls.kt")
|
||||||
public void testStarsInFunctionCalls() throws Exception {
|
public void testStarsInFunctionCalls() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/StarsInFunctionCalls.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/StarsInFunctionCalls.kt");
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion) {
|
|||||||
DataClassInheritance(KOTLIN_1_1),
|
DataClassInheritance(KOTLIN_1_1),
|
||||||
InlineProperties(KOTLIN_1_1),
|
InlineProperties(KOTLIN_1_1),
|
||||||
DestructuringLambdaParameters(KOTLIN_1_1),
|
DestructuringLambdaParameters(KOTLIN_1_1),
|
||||||
|
SingleUnderscoreForParameterName(KOTLIN_1_1)
|
||||||
;
|
;
|
||||||
|
|
||||||
val presentableText: String
|
val presentableText: String
|
||||||
|
|||||||
Reference in New Issue
Block a user