From 2c837184522f07a16ca1df46b050093433ed82eb Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 25 May 2017 17:08:52 +0300 Subject: [PATCH] Prohibit having duplicate parameter names in functional types #KT-15804 Fixed --- .../org/jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../org/jetbrains/kotlin/resolve/TypeResolver.kt | 14 ++++++++++++++ .../DuplicateParameterNamesInFunctionType.kt | 7 +++++++ .../DuplicateParameterNamesInFunctionType.txt | 4 ++++ .../kotlin/checkers/DiagnosticsTestGenerated.java | 6 ++++++ 6 files changed, 33 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.kt create mode 100644 compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 6afacbe36ba..4639a35e169 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -79,6 +79,7 @@ public interface Errors { DiagnosticFactory1.create(ERROR, FOR_REDECLARATION); DiagnosticFactory1 PACKAGE_OR_CLASSIFIER_REDECLARATION = DiagnosticFactory1.create(ERROR, FOR_REDECLARATION); + DiagnosticFactory0 DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR, DECLARATION_NAME); DiagnosticFactory1 EXTENSION_SHADOWED_BY_MEMBER = DiagnosticFactory1.create(WARNING, FOR_REDECLARATION); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index f048c18a8ca..9c51f658de0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -114,6 +114,7 @@ public class DefaultErrorMessages { MAP.put(REDECLARATION, "Conflicting declarations: {0}", commaSeparated(COMPACT_WITH_MODIFIERS)); MAP.put(PACKAGE_OR_CLASSIFIER_REDECLARATION, "Redeclaration: {0}", STRING); + MAP.put(DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE, "Duplicate parameter name in function type"); MAP.put(NAME_SHADOWING, "Name shadowed: {0}", STRING); MAP.put(ACCESSOR_PARAMETER_NAME_SHADOWING, "Accessor parameter name 'field' is shadowed by backing field variable"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 724bd250f34..f53e46f5b6f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.utils.findFirstFromMeAndParent import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.types.* @@ -55,6 +56,7 @@ import org.jetbrains.kotlin.types.Variance.* import org.jetbrains.kotlin.types.typeUtil.containsTypeAliasParameters import org.jetbrains.kotlin.types.typeUtil.containsTypeAliases import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class TypeResolver( private val annotationResolver: AnnotationResolver, @@ -231,6 +233,7 @@ class TypeResolver( val receiverType = if (receiverTypeRef == null) null else resolveType(c.noBareTypes(), receiverTypeRef) val parameterDescriptors = resolveParametersOfFunctionType(type.parameters) + checkParametersOfFunctionType(parameterDescriptors) val returnTypeRef = type.returnTypeReference val returnType = if (returnTypeRef != null) resolveType(c.noBareTypes(), returnTypeRef) @@ -245,6 +248,17 @@ class TypeResolver( )) } + private fun checkParametersOfFunctionType(parameterDescriptors: List) { + val parametersByName = parameterDescriptors.filter { !it.name.isSpecial }.groupBy { it.name } + for (parametersGroup in parametersByName.values) { + if (parametersGroup.size < 2) continue + for (parameter in parametersGroup) { + val ktParameter = parameter.source.getPsi()?.safeAs() ?: continue + c.trace.report(DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE.on(ktParameter)) + } + } + } + private fun resolveParametersOfFunctionType(parameters: List): List { class ParameterOfFunctionTypeDescriptor( containingDeclaration: DeclarationDescriptor, diff --git a/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.kt b/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.kt new file mode 100644 index 00000000000..78f37b2fc17 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.kt @@ -0,0 +1,7 @@ +fun test0(f: (String, String) -> Unit) { + f("", "") +} + +fun test1(f: (a: Int, a: Int) -> Unit) { + f(1, 1) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.txt b/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.txt new file mode 100644 index 00000000000..60682e6291c --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.txt @@ -0,0 +1,4 @@ +package + +public fun test0(/*0*/ f: (kotlin.String, kotlin.String) -> kotlin.Unit): kotlin.Unit +public fun test1(/*0*/ f: (a: kotlin.Int, a: kotlin.Int) -> kotlin.Unit): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 21e2f510b2e..e71fb2470b5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -16099,6 +16099,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("DuplicateParameterNamesInFunctionType.kt") + public void testDuplicateParameterNamesInFunctionType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/DuplicateParameterNamesInFunctionType.kt"); + doTest(fileName); + } + @TestMetadata("EnumName.kt") public void testEnumName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/EnumName.kt");