From 1c5df773c537b9d5d2d4b71ed87a4399be700ac2 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 19 Mar 2014 17:57:18 +0400 Subject: [PATCH] Disallow named arguments for Java methods Since they don't have stable names: they're (sometimes) loaded from the bytecode, which (sometimes) doesn't contain parameter names --- .../jet/lang/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../ValueArgumentsToParametersMapper.java | 12 +++++++-- .../namedArguments/disallowForJavaMethods.kt | 27 +++++++++++++++++++ .../namedArgumentsAndDefaultValues.kt} | 0 .../checkers/JetDiagnosticsTestGenerated.java | 26 +++++++++++++----- .../classInheritorsSearch.kt | 12 ++++----- .../declarationsSearch/overridersSearch.kt | 15 +++-------- .../refactoring/move/AbstractJetMoveTest.kt | 11 ++++---- .../k2js/translate/context/UsageTracker.kt | 2 +- 10 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/namedArguments/disallowForJavaMethods.kt rename compiler/testData/diagnostics/tests/{NamedArgumentsAndDefaultValues.kt => namedArguments/namedArgumentsAndDefaultValues.kt} (100%) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index dcc4326c989..97c816c7d69 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -321,6 +321,7 @@ public interface Errors { DiagnosticFactory0 ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 NAMED_PARAMETER_NOT_FOUND = DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE); + DiagnosticFactory0 NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_VARARG_SPREAD = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index aeae9274f70..f1fbde96f95 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -107,6 +107,7 @@ public class DefaultErrorMessages { MAP.put(MIXING_NAMED_AND_POSITIONED_ARGUMENTS, "Mixing named and positioned arguments is not allowed"); MAP.put(ARGUMENT_PASSED_TWICE, "An argument is already passed for this parameter"); MAP.put(NAMED_PARAMETER_NOT_FOUND, "Cannot find a parameter with this name: {0}", ELEMENT_TEXT); + MAP.put(NAMED_ARGUMENTS_NOT_ALLOWED, "Named arguments are not allowed for non-Kotlin functions"); MAP.put(VARARG_OUTSIDE_PARENTHESES, "Passing value as a vararg is only allowed inside a parenthesized argument list"); MAP.put(NON_VARARG_SPREAD, "The spread operator (*foo) may only be applied in a vararg position"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java index bcd10225dab..8284eae27f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java @@ -25,14 +25,19 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.Call; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.psi.ValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; @@ -150,6 +155,9 @@ import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMap JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression(); ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName()); + if (!candidateCall.getCandidateDescriptor().hasStableParameterNames()) { + report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference)); + } if (valueParameterDescriptor == null) { report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference)); unmappedArguments.add(argument); diff --git a/compiler/testData/diagnostics/tests/namedArguments/disallowForJavaMethods.kt b/compiler/testData/diagnostics/tests/namedArguments/disallowForJavaMethods.kt new file mode 100644 index 00000000000..2eae517cffd --- /dev/null +++ b/compiler/testData/diagnostics/tests/namedArguments/disallowForJavaMethods.kt @@ -0,0 +1,27 @@ +// FILE: JavaSuperClass.java + +class JavaSuperClass { + void foo(int javaName) {} + + void multipleParameters(int first, long second, String third) {} +} + +// FILE: 1.kt + +fun directInvocation() = JavaSuperClass().foo(javaName = 1) + +open class KotlinSubClass : JavaSuperClass() + +fun viaFakeOverride() = KotlinSubClass().foo(javaName = 2) + +class KotlinSubSubClass : KotlinSubClass() { + override fun foo(kotlinName: Int) {} +} + +fun viaRealOverride() = KotlinSubSubClass().foo(kotlinName = 3) + + +fun unresolvedParameter() = JavaSuperClass().foo(nonexistentName = 4) + + +fun multipleParameters() = JavaSuperClass().multipleParameters(first = 1, second = 2L, third = "3") diff --git a/compiler/testData/diagnostics/tests/NamedArgumentsAndDefaultValues.kt b/compiler/testData/diagnostics/tests/namedArguments/namedArgumentsAndDefaultValues.kt similarity index 100% rename from compiler/testData/diagnostics/tests/NamedArgumentsAndDefaultValues.kt rename to compiler/testData/diagnostics/tests/namedArguments/namedArgumentsAndDefaultValues.kt diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index ea5be3549be..c6616290bc2 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -33,7 +33,7 @@ import org.jetbrains.jet.checkers.AbstractJetDiagnosticsTest; @InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class}) public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { @TestMetadata("compiler/testData/diagnostics/tests") - @InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class}) + @InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class}) public static class Tests extends AbstractJetDiagnosticsTest { @TestMetadata("Abstract.kt") public void testAbstract() throws Exception { @@ -309,11 +309,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/MultipleBounds.kt"); } - @TestMetadata("NamedArgumentsAndDefaultValues.kt") - public void testNamedArgumentsAndDefaultValues() throws Exception { - doTest("compiler/testData/diagnostics/tests/NamedArgumentsAndDefaultValues.kt"); - } - @TestMetadata("Nullability.kt") public void testNullability() throws Exception { doTest("compiler/testData/diagnostics/tests/Nullability.kt"); @@ -4765,6 +4760,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } + @TestMetadata("compiler/testData/diagnostics/tests/namedArguments") + public static class NamedArguments extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInNamedArguments() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/namedArguments"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("disallowForJavaMethods.kt") + public void testDisallowForJavaMethods() throws Exception { + doTest("compiler/testData/diagnostics/tests/namedArguments/disallowForJavaMethods.kt"); + } + + @TestMetadata("namedArgumentsAndDefaultValues.kt") + public void testNamedArgumentsAndDefaultValues() throws Exception { + doTest("compiler/testData/diagnostics/tests/namedArguments/namedArgumentsAndDefaultValues.kt"); + } + + } + @TestMetadata("compiler/testData/diagnostics/tests/nullabilityAndAutoCasts") public static class NullabilityAndAutoCasts extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInNullabilityAndAutoCasts() throws Exception { @@ -7012,6 +7025,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { suite.addTestSuite(J_k.class); suite.addTest(Jdk_annotations.innerSuite()); suite.addTestSuite(Library.class); + suite.addTestSuite(NamedArguments.class); suite.addTestSuite(NullabilityAndAutoCasts.class); suite.addTestSuite(NullableTypes.class); suite.addTestSuite(Numbers.class); diff --git a/idea/src/org/jetbrains/jet/plugin/search/declarationsSearch/classInheritorsSearch.kt b/idea/src/org/jetbrains/jet/plugin/search/declarationsSearch/classInheritorsSearch.kt index 6ac6782fd27..7dbf715b827 100644 --- a/idea/src/org/jetbrains/jet/plugin/search/declarationsSearch/classInheritorsSearch.kt +++ b/idea/src/org/jetbrains/jet/plugin/search/declarationsSearch/classInheritorsSearch.kt @@ -18,12 +18,10 @@ package org.jetbrains.jet.plugin.search.declarationsSearch import com.intellij.psi.PsiClass import com.intellij.util.Query -import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.PsiModifier import com.intellij.psi.PsiAnonymousClass import org.jetbrains.jet.lang.psi.JetClassOrObject import org.jetbrains.jet.asJava.LightClassUtil -import com.intellij.psi.search.searches.DirectClassInheritorsSearch import com.intellij.psi.PsiElement import com.intellij.psi.search.searches.ClassInheritorsSearch import com.intellij.util.EmptyQuery @@ -37,11 +35,11 @@ public fun HierarchySearchRequest.searchInheritors(): Query(PsiMe val classTraverser = object : HierarchyTraverser { override fun nextElements(current: PsiClass): Iterable = DirectClassInheritorsSearch.search( - aClass = current, - scope = GlobalSearchScope.allScope(current.getProject()), - checkInheritance = true, - includeAnonymous = true + current, + GlobalSearchScope.allScope(current.getProject()), + /* checkInheritance = */ true, + /* includeAnonymous = */ true ) override fun shouldDescend(element: PsiClass): Boolean = diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/move/AbstractJetMoveTest.kt b/idea/tests/org/jetbrains/jet/plugin/refactoring/move/AbstractJetMoveTest.kt index 0b187ffb52f..dc580af21f4 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/move/AbstractJetMoveTest.kt +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/move/AbstractJetMoveTest.kt @@ -51,7 +51,6 @@ import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectori import com.intellij.refactoring.move.MoveHandler import org.jetbrains.jet.getString import org.jetbrains.jet.getNullableString -import org.jetbrains.jet.lang.psi.JetClassOrObject import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsProcessor import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsOptions import org.jetbrains.jet.lang.psi.JetNamedDeclaration @@ -240,11 +239,11 @@ enum class MoveAction { val targetFile = config.getString("targetFile") MoveHandler.doMove( - project = project, - elements = array(mainFile), - targetContainer = PsiManager.getInstance(project).findFile(rootDir.findFileByRelativePath(targetFile)!!)!!, - dataContext = null, - callback = null + project, + array(mainFile), + PsiManager.getInstance(project).findFile(rootDir.findFileByRelativePath(targetFile)!!)!!, + /* dataContext = */ null, + /* callback = */ null ) } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.kt b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.kt index c48b98d5728..c52fedadadb 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/UsageTracker.kt @@ -55,7 +55,7 @@ class UsageTracker( } private fun captureIfNeed(descriptor: CallableDescriptor?) { - if (descriptor == null || isCaptured(descriptor) || isAncestor(containingDescriptor, descriptor, strict = true)) return + if (descriptor == null || isCaptured(descriptor) || isAncestor(containingDescriptor, descriptor, /* strict = */ true)) return parent?.captureIfNeed(descriptor)