Check lambda parameter for name shadowing
#KT-5160 Fixed
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.types.ErrorUtils
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
||||||
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
||||||
@@ -375,6 +376,10 @@ class FunctionDescriptorResolver(
|
|||||||
|
|
||||||
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor,
|
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor,
|
||||||
valueParameter, i, type, trace)
|
valueParameter, i, type, trace)
|
||||||
|
|
||||||
|
// Do not report NAME_SHADOWING for lambda destructured parameters as they may be not fully resolved at this time
|
||||||
|
ExpressionTypingUtils.checkVariableShadowing(parameterScope, trace, valueParameterDescriptor)
|
||||||
|
|
||||||
parameterScope.addVariableDescriptor(valueParameterDescriptor)
|
parameterScope.addVariableDescriptor(valueParameterDescriptor)
|
||||||
result.add(valueParameterDescriptor)
|
result.add(valueParameterDescriptor)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -30,8 +30,8 @@ fun foo(y: IntArray) {
|
|||||||
|
|
||||||
@Ann1 y[0]
|
@Ann1 y[0]
|
||||||
|
|
||||||
@Ann1 <!UNUSED_LAMBDA_EXPRESSION!>{ x: Int -> x }<!>
|
@Ann1 <!UNUSED_LAMBDA_EXPRESSION!>{ <!NAME_SHADOWING!>x<!>: Int -> x }<!>
|
||||||
@Ann1 { x: Int -> x }(1)
|
@Ann1 { <!NAME_SHADOWING!>x<!>: Int -> x }(1)
|
||||||
@Ann1 object { fun foo() = 1 }
|
@Ann1 object { fun foo() = 1 }
|
||||||
@Ann1 object { fun foo() = 1 }.foo()
|
@Ann1 object { fun foo() = 1 }.foo()
|
||||||
|
|
||||||
@@ -45,8 +45,8 @@ fun foo(y: IntArray) {
|
|||||||
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> + 6 * 2 > 0
|
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> + 6 * 2 > 0
|
||||||
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> * 6 + 2 > 0
|
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> * 6 + 2 > 0
|
||||||
|
|
||||||
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 object { operator fun plus(x: Int) = 1 }<!> + 1
|
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 object { operator fun plus(<!NAME_SHADOWING!>x<!>: Int) = 1 }<!> + 1
|
||||||
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 object { operator fun plus(x: Int) = 1 }<!> + 1 * 4 > 0
|
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 object { operator fun plus(<!NAME_SHADOWING!>x<!>: Int) = 1 }<!> + 1 * 4 > 0
|
||||||
|
|
||||||
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> foo z + 8
|
<!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!>@Ann1 x<!> foo z + 8
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -9,5 +9,5 @@ fun transform(i: Int, tr: (<!WRONG_ANNOTATION_TARGET!>@special<!> Int) -> Int):
|
|||||||
fun foo(i: Int): Int {
|
fun foo(i: Int): Int {
|
||||||
val j = @special i + 1
|
val j = @special i + 1
|
||||||
if (j == 1) return foo(@special 42)
|
if (j == 1) return foo(@special 42)
|
||||||
return transform(@special j, @special { i: @base Int -> <!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!><!WRONG_ANNOTATION_TARGET!>@base<!> i<!> * 2 })
|
return transform(@special j, @special { <!NAME_SHADOWING!>i<!>: @base Int -> <!ANNOTATIONS_ON_BLOCK_LEVEL_EXPRESSION_ON_THE_SAME_LINE!><!WRONG_ANNOTATION_TARGET!>@base<!> i<!> * 2 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
data class A1(val <!REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int, val y: String, val <!REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int) {
|
data class A1(val <!REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int, val y: String, val <!NAME_SHADOWING, REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int) {
|
||||||
val z = ""
|
val z = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -1,10 +1,10 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
|
||||||
fun test(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int) {
|
fun test(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int) {
|
||||||
fun test2(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int) {
|
fun test2(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x1<!>: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x2<!>: Int) {
|
||||||
class LocalClass(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int) {
|
class LocalClass(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x1<!>: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x2<!>: Int) {
|
||||||
constructor(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int, xx: Int) {}
|
constructor(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x1<!>: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x2<!>: Int, xx: Int) {}
|
||||||
}
|
}
|
||||||
fun test3(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x1: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> x2: Int) {}
|
fun test3(<!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x1<!>: Int, <!MULTIPLE_VARARG_PARAMETERS!>vararg<!> <!NAME_SHADOWING!>x2<!>: Int) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ fun bar() {
|
|||||||
_ checkType { _<String>() }
|
_ checkType { _<String>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
foo { <!REDECLARATION, REDECLARATION, UNUSED_ANONYMOUS_PARAMETER!>`_`<!>, <!REDECLARATION, REDECLARATION!>`_`<!> ->
|
foo { <!REDECLARATION, REDECLARATION, UNUSED_ANONYMOUS_PARAMETER!>`_`<!>, <!NAME_SHADOWING, REDECLARATION, REDECLARATION!>`_`<!> ->
|
||||||
_ checkType { _<String>() }
|
_ checkType { _<String>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ fun bar(b: B): String {
|
|||||||
// Ok: local variable
|
// Ok: local variable
|
||||||
val tmp = if (b is A && b is C) b else null
|
val tmp = if (b is A && b is C) b else null
|
||||||
// Error: local function
|
// Error: local function
|
||||||
fun <!IMPLICIT_INTERSECTION_TYPE!>foo<!>(b: B) = if (b is A && b is C) b else null
|
fun <!IMPLICIT_INTERSECTION_TYPE!>foo<!>(<!NAME_SHADOWING!>b<!>: B) = if (b is A && b is C) b else null
|
||||||
return tmp.toString()
|
return tmp.toString()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
inline fun foo(f: () -> Unit) {
|
inline fun foo(f: () -> Unit) {
|
||||||
val ff = { f: () -> Unit ->
|
val ff = { <!NAME_SHADOWING!>f<!>: () -> Unit ->
|
||||||
f.invoke()
|
f.invoke()
|
||||||
}
|
}
|
||||||
ff(<!USAGE_IS_NOT_INLINABLE!>f<!>)
|
ff(<!USAGE_IS_NOT_INLINABLE!>f<!>)
|
||||||
|
|||||||
+1
-1
@@ -37,6 +37,6 @@ fun test(b: B<out Number>) {
|
|||||||
b.foo(Number::foobar)
|
b.foo(Number::foobar)
|
||||||
|
|
||||||
b.baz {
|
b.baz {
|
||||||
b -> b checkType { _<B<out Number>>() }
|
<!NAME_SHADOWING!>b<!> -> b checkType { _<B<out Number>>() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun foo1(i: (Int) -> Unit) {}
|
||||||
|
fun foo2(i: (Int, Int) -> Unit) {}
|
||||||
|
fun foo3(i: (Pair) -> Unit) {}
|
||||||
|
|
||||||
|
fun bar(x: Int, y: Int) {
|
||||||
|
foo1 { <!NAME_SHADOWING!>x<!> -> <!UNUSED_EXPRESSION!>x<!> }
|
||||||
|
foo2 { <!NAME_SHADOWING!>x<!>: Int, <!NAME_SHADOWING!>y<!>: Int -> x + y }
|
||||||
|
foo3 { (x, y) -> x + y }
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Pair(val a: Int, val b: Int)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun bar(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Unit
|
||||||
|
public fun foo1(/*0*/ i: (kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun foo2(/*0*/ i: (kotlin.Int, kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun foo3(/*0*/ i: (Pair) -> kotlin.Unit): kotlin.Unit
|
||||||
|
|
||||||
|
public final data class Pair {
|
||||||
|
public constructor Pair(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int)
|
||||||
|
public final val a: kotlin.Int
|
||||||
|
public final val b: kotlin.Int
|
||||||
|
public final operator /*synthesized*/ fun component1(): kotlin.Int
|
||||||
|
public final operator /*synthesized*/ fun component2(): kotlin.Int
|
||||||
|
public final /*synthesized*/ fun copy(/*0*/ a: kotlin.Int = ..., /*1*/ b: kotlin.Int = ...): Pair
|
||||||
|
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
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
fun ff(): Int {
|
fun ff(): Int {
|
||||||
var i = 1
|
var i = 1
|
||||||
<!UNUSED_LAMBDA_EXPRESSION!>{ i: Int -> i }<!>
|
<!UNUSED_LAMBDA_EXPRESSION!>{ <!NAME_SHADOWING!>i<!>: Int -> i }<!>
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ fun foo(x: Int, y: String = <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLA
|
|||||||
|
|
||||||
listOf<String>()
|
listOf<String>()
|
||||||
.map<String, String> { <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!> }
|
.map<String, String> { <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!> }
|
||||||
.filter(fun(x: String): Boolean { <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!> })
|
.filter(fun(<!NAME_SHADOWING!>x<!>: String): Boolean { <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!> })
|
||||||
|
|
||||||
<!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!>
|
<!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ fun foo() {
|
|||||||
manyArgumentsBuilder<String>({}, { "" }, { 1 })
|
manyArgumentsBuilder<String>({}, { "" }, { 1 })
|
||||||
manyArgumentsBuilder<String>({}, { <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> }, { 2 })
|
manyArgumentsBuilder<String>({}, { <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> }, { 2 })
|
||||||
|
|
||||||
severalParamsInLambda { x, y ->
|
severalParamsInLambda { <!NAME_SHADOWING!>x<!>, <!NAME_SHADOWING!>y<!> ->
|
||||||
x checkType { _<String>() }
|
x checkType { _<String>() }
|
||||||
y checkType { _<Int>() }
|
y checkType { _<Int>() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19174,6 +19174,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/shadowing"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/shadowing"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ShadowLambdaParameter.kt")
|
||||||
|
public void testShadowLambdaParameter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/shadowing/ShadowLambdaParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ShadowMultiDeclarationWithFunParameter.kt")
|
@TestMetadata("ShadowMultiDeclarationWithFunParameter.kt")
|
||||||
public void testShadowMultiDeclarationWithFunParameter() throws Exception {
|
public void testShadowMultiDeclarationWithFunParameter() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/shadowing/ShadowMultiDeclarationWithFunParameter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user