Prohibit having duplicate parameter names in functional types

#KT-15804 Fixed
This commit is contained in:
Dmitry Petrov
2017-05-25 17:08:52 +03:00
parent 9908212c99
commit 2c83718452
6 changed files with 33 additions and 0 deletions
@@ -79,6 +79,7 @@ public interface Errors {
DiagnosticFactory1.create(ERROR, FOR_REDECLARATION);
DiagnosticFactory1<PsiElement, String> PACKAGE_OR_CLASSIFIER_REDECLARATION =
DiagnosticFactory1.create(ERROR, FOR_REDECLARATION);
DiagnosticFactory0<KtParameter> DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
DiagnosticFactory1<KtDeclaration, CallableMemberDescriptor> EXTENSION_SHADOWED_BY_MEMBER =
DiagnosticFactory1.create(WARNING, FOR_REDECLARATION);
@@ -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");
@@ -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<VariableDescriptor>) {
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<KtParameter>() ?: continue
c.trace.report(DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE.on(ktParameter))
}
}
}
private fun resolveParametersOfFunctionType(parameters: List<KtParameter>): List<VariableDescriptor> {
class ParameterOfFunctionTypeDescriptor(
containingDeclaration: DeclarationDescriptor,
@@ -0,0 +1,7 @@
fun test0(f: (String, String) -> Unit) {
f("", "")
}
fun test1(f: (<!DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE!>a<!>: Int, <!DUPLICATE_PARAMETER_NAME_IN_FUNCTION_TYPE!>a<!>: Int) -> Unit) {
f(1, 1)
}
@@ -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
@@ -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");