From 62e87c873c42a579c3b399f2292d7dd40255e96d Mon Sep 17 00:00:00 2001 From: e5l Date: Fri, 11 Aug 2017 16:45:48 +0300 Subject: [PATCH] Add annotation for parameter name in signatures --- compiler.tests-common/build.gradle.kts | 1 + .../SignaturesPropagationData.java | 22 +++-- .../reorderedParameterNames.kt | 31 ++++++ .../emptyParameterName.kt | 27 +++++ .../emptyParameterName.txt | 13 +++ .../overridesParameterName.kt | 98 +++++++++++++++++++ .../overridesParameterName.txt | 67 +++++++++++++ .../reorderedParameterNames.kt | 17 ++++ .../reorderedParameterNames.txt | 11 +++ .../signatureAnnotations/sameParameterName.kt | 17 ++++ .../sameParameterName.txt | 11 +++ .../specialCharsParameterName.kt | 24 +++++ .../specialCharsParameterName.txt | 12 +++ .../stableParameterName.kt | 20 ++++ .../stableParameterName.txt | 25 +++++ .../signatureAnnotations/StableName.java | 11 +++ .../signatureAnnotations/StableName.txt | 6 ++ .../checkers/KotlinMultiFileTestWithJava.java | 24 ++++- .../kotlin/codegen/CodegenTestCase.java | 21 +++- .../forTestCompile/ForTestCompileRuntime.java | 5 + .../jvm/compiler/LoadDescriptorUtil.java | 23 ++++- .../ir/IrBlackBoxCodegenTestGenerated.java | 15 +++ .../checkers/DiagnosticsTestGenerated.java | 45 +++++++++ .../DiagnosticsUsingJavacTestGenerated.java | 45 +++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 15 +++ .../LightAnalysisModeTestGenerated.java | 15 +++ .../jvm/compiler/LoadJavaTestGenerated.java | 15 +++ ...JavaWithFastClassReadingTestGenerated.java | 15 +++ .../LoadJavaUsingJavacTestGenerated.java | 15 +++ ...mRuntimeDescriptorLoaderTestGenerated.java | 15 +++ .../kotlin/load/java/JvmAnnotationNames.java | 2 + .../kotlin/load/java/descriptors/util.kt | 14 +++ .../java/lazy/descriptors/LazyJavaScope.kt | 16 ++- .../semantics/JsCodegenBoxTestGenerated.java | 9 ++ .../tools/android-annotations/build.gradle | 36 +++++++ .../src/kotlin/Annotations.kt | 24 +++++ settings.gradle | 2 + 37 files changed, 766 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.txt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.txt create mode 100644 compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java create mode 100644 compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.txt create mode 100644 libraries/tools/android-annotations/build.gradle create mode 100644 libraries/tools/android-annotations/src/kotlin/Annotations.kt diff --git a/compiler.tests-common/build.gradle.kts b/compiler.tests-common/build.gradle.kts index 41b9d7e94db..1602295b908 100644 --- a/compiler.tests-common/build.gradle.kts +++ b/compiler.tests-common/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { compileOnly(project(":plugins:android-extensions-compiler")) compile(project(":kotlin-test:kotlin-test-jvm")) compile(project(":compiler:tests-common-jvm6")) + compile(project(":android-annotations")) compile(commonDep("junit:junit")) compile(ideaSdkCoreDeps("intellij-core")) compile(ideaSdkDeps("openapi", "idea", "idea_rt")) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java index fb99890befd..6c9477dc6f3 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java @@ -22,10 +22,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.annotations.Annotations; +import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor; +import org.jetbrains.kotlin.load.java.descriptors.UtilKt; import org.jetbrains.kotlin.load.java.structure.JavaMethod; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; @@ -66,10 +67,12 @@ public class SignaturesPropagationData { JavaMethodDescriptor autoMethodDescriptor = createAutoMethodDescriptor(containingClass, method, autoReturnType, autoValueParameters, autoTypeParameters); + boolean hasStableParameterNames = autoValueParameters.stream().allMatch(it -> UtilKt.getParameterNameAnnotation(it) != null); + superFunctions = getSuperFunctionsForMethod(method, autoMethodDescriptor, containingClass); modifiedValueParameters = superFunctions.isEmpty() - ? new ValueParameters(null, autoValueParameters, /* stableParameterNames = */false) - : modifyValueParametersAccordingToSuperMethods(autoValueParameters); + ? new ValueParameters(null, autoValueParameters, hasStableParameterNames) + : modifyValueParametersAccordingToSuperMethods(autoValueParameters, hasStableParameterNames); } @NotNull @@ -118,7 +121,10 @@ public class SignaturesPropagationData { signatureErrors.add(error); } - private ValueParameters modifyValueParametersAccordingToSuperMethods(@NotNull List parameters) { + private ValueParameters modifyValueParametersAccordingToSuperMethods( + @NotNull List parameters, + boolean annotatedWithParameterName + ) { KotlinType resultReceiverType = null; List resultParameters = new ArrayList<>(parameters.size()); @@ -159,12 +165,15 @@ public class SignaturesPropagationData { } } + AnnotationDescriptor currentName = UtilKt.getParameterNameAnnotation(originalParam); + boolean shouldTakeOldName = currentName == null && stableName != null; + resultParameters.add(new ValueParameterDescriptorImpl( originalParam.getContainingDeclaration(), null, shouldBeExtension ? originalIndex - 1 : originalIndex, originalParam.getAnnotations(), - stableName != null ? stableName : originalParam.getName(), + shouldTakeOldName ? stableName : originalParam.getName(), altType, originalParam.declaresDefaultValue(), originalParam.isCrossinline(), @@ -175,7 +184,8 @@ public class SignaturesPropagationData { } } - boolean hasStableParameterNames = CollectionsKt.any(superFunctions, CallableDescriptor::hasStableParameterNames); + boolean hasStableParameterNames = + annotatedWithParameterName || CollectionsKt.any(superFunctions, CallableDescriptor::hasStableParameterNames); return new ValueParameters(resultReceiverType, resultParameters, hasStableParameterNames); } diff --git a/compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt b/compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt new file mode 100644 index 00000000000..6227b07240c --- /dev/null +++ b/compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt @@ -0,0 +1,31 @@ +// TARGET_BACKEND: JVM + +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +public class A { + public int connect(@ParameterName("host") int host, @ParameterName("port") int port) { + return host; + } +} + +// FILE: test.kt +fun box(): String { + val test = A() + + if (test.connect(host = 42, port = 8080) != 42) { + return "FAIL 1" + } + + if (test.connect(port = 1234, host = 5678) != 5678) { + return "FAIL 2" + } + + if (test.connect(9876, 4321) != 9876) { + return "FAIL 3" + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt new file mode 100644 index 00000000000..769af592f37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt @@ -0,0 +1,27 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public void emptyName(@ParameterName("") String first, @ParameterName("ok") int second) { + } + + public void missingName(@ParameterName() String first) { + } + + public void numberName(@ParameterName(42) String first) { + } +} + +// FILE: test.kt +fun main() { + val test = A() + test.emptyName("first", 42) + test.emptyName("first", ok = 42) + + test.missingName(`first` = "arg") + test.missingName("arg") + + test.numberName("first") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.txt new file mode 100644 index 00000000000..1e68dcac9a0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.txt @@ -0,0 +1,13 @@ +package + +public fun main(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open fun emptyName(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "") first: kotlin.String!, /*1*/ @kotlin.annotations.jvm.internal.ParameterName(value = "ok") ok: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun missingName(/*0*/ @kotlin.annotations.jvm.internal.ParameterName first: kotlin.String!): kotlin.Unit + public open fun numberName(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = 42) first: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt new file mode 100644 index 00000000000..bb64c719102 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt @@ -0,0 +1,98 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS + +import kotlin.annotations.jvm.internal.*; + +class A { + public void call(@ParameterName("foo") String arg) { + } +} + +// FILE: B.java +import kotlin.annotations.jvm.internal.*; + +class B extends A { + public void call(@ParameterName("bar") String arg) { + } +} + +// FILE: C.java + +class C extends A { + public void call(String arg) { + } +} + +// FILE: D.kt +open class D { + open fun call(foo: String) { + } +} + +// FILE: E.java +import kotlin.annotations.jvm.internal.*; + +class E extends D { + public void call(@ParameterName("baz") String bar) { + } +} + +// FILE: F.java +class F extends D { + public void call(String baaam) { + } +} + + +// FILE: G.java +import kotlin.annotations.jvm.internal.*; + +class G { + public void foo(String bar, @ParameterName("foo") String baz) { + } +} + +// FILE: H.java +class H extends G { + public void foo(String baz, String bam) { + } +} + +// FILE: test.kt +fun main() { + val a = A() + val b = B() + val c = C() + + a.call(foo = "hello") + a.call(arg = "hello") + a.call("hello") + + b.call(foo = "hello") + b.call(arg = "hello") + b.call(bar = "hello") + b.call("hello") + + c.call(foo = "hello") + c.call(arg = "hello") + c.call("hello") + + val e = E() + val f = F() + + e.call(foo = "hello") + e.call(bar = "hello") + e.call(baz = "hello") + e.call("hello") + + f.call(foo = "hello") + f.call(baaam = "hello") + f.call("hello") + + val g = G() + val h = H() + g.foo("ok", foo = "hohoho") + g.foo("ok", "hohoho") + h.foo("ok", foo = "hohoho") + h.foo("ok", "hohoho") +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.txt new file mode 100644 index 00000000000..1b5630b0369 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.txt @@ -0,0 +1,67 @@ +package + +public fun main(): kotlin.Unit + +public/*package*/ open class A { + public/*package*/ constructor A() + public open fun call(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "foo") foo: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class B : A { + public/*package*/ constructor B() + public open override /*1*/ fun call(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "bar") bar: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class C : A { + public/*package*/ constructor C() + public open override /*1*/ fun call(/*0*/ foo: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class D { + public constructor D() + public open fun call(/*0*/ foo: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class E : D { + public/*package*/ constructor E() + public open override /*1*/ fun call(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "baz") baz: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class F : D { + public/*package*/ constructor F() + public open override /*1*/ fun call(/*0*/ foo: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class G { + public/*package*/ constructor G() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ bar: kotlin.String!, /*1*/ @kotlin.annotations.jvm.internal.ParameterName(value = "foo") foo: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public/*package*/ open class H : G { + public/*package*/ constructor H() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(/*0*/ baz: kotlin.String!, /*1*/ bam: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt new file mode 100644 index 00000000000..3b593be43c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt @@ -0,0 +1,17 @@ + +// FILE: A.java +// ANDROID_ANNOTATIONS +import kotlin.annotations.jvm.internal.*; + +public class A { + public void connect(@ParameterName("host") String host, @ParameterName("port") int port) { + } +} + +// FILE: test.kt +fun main() { + val test = A() + test.connect("127.0.0.1", 8080) + test.connect(host = "127.0.0.1", port = 8080) + test.connect(port = 8080, host = "127.0.0.1") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.txt new file mode 100644 index 00000000000..67824fe0040 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.txt @@ -0,0 +1,11 @@ +package + +public fun main(): kotlin.Unit + +public open class A { + public constructor A() + public open fun connect(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "host") host: kotlin.String!, /*1*/ @kotlin.annotations.jvm.internal.ParameterName(value = "port") port: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt new file mode 100644 index 00000000000..c6bacf0a039 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt @@ -0,0 +1,17 @@ + +// FILE: A.java +// ANDROID_ANNOTATIONS +import kotlin.annotations.jvm.internal.*; + +public class A { + public void same(@ParameterName("ok") String first, @ParameterName("ok") String second) { + } +} + +// FILE: test.kt +fun main() { + val test = A() + test.same("hello", "world") + test.same(ok = "hello", ok = world) + test.same("hello", ok = "world") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.txt new file mode 100644 index 00000000000..2f181c13e73 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.txt @@ -0,0 +1,11 @@ +package + +public fun main(): kotlin.Unit + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun same(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "ok") ok: kotlin.String!, /*1*/ @kotlin.annotations.jvm.internal.ParameterName(value = "ok") second: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt new file mode 100644 index 00000000000..b9541b7e646 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt @@ -0,0 +1,24 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS +import kotlin.annotations.jvm.internal.*; +import kotlin.internal.*; + +public class A { + public void dollarName(@ParameterName("$") String host) { + } + + public void numberName(@ParameterName("42") String field) { + } +} + +// FILE: test.kt +fun main() { + val test = A() + test.dollarName(`$` = "hello") + test.dollarName("hello") + test.dollarName(host = "hello") + + test.numberName(`42` = "world") + test.numberName("world") + test.numberName(field = "world") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.txt new file mode 100644 index 00000000000..299fc9b6651 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.txt @@ -0,0 +1,12 @@ +package + +public fun main(): kotlin.Unit + +public open class A { + public constructor A() + public open fun dollarName(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "$") `$`: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun numberName(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "42") 42: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt new file mode 100644 index 00000000000..44c47d2bfc3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt @@ -0,0 +1,20 @@ +// FILE: A.java +// ANDROID_ANNOTATIONS +import kotlin.annotations.jvm.internal.*; + + +public class A { + public void foo(@ParameterName("hello") String world) {} +} + +// FILE: B.kt + +class B : A() { + override fun foo(hello: String) {} +} + +// FILE: C.kt + +class C : A() { +} + diff --git a/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.txt b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.txt new file mode 100644 index 00000000000..a46b3ad3bac --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.txt @@ -0,0 +1,25 @@ +package + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "hello") hello: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B : A { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun foo(/*0*/ hello: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C : A { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun foo(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "hello") hello: kotlin.String!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java b/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java new file mode 100644 index 00000000000..f1da59361b5 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java @@ -0,0 +1,11 @@ +// SKIP_IN_RUNTIME_TEST +// ANDROID_ANNOTATIONS + +package test; + +import kotlin.annotations.jvm.internal.*; + +public class StableName { + public void connect(@ParameterName("host") String host) { + } +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.txt b/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.txt new file mode 100644 index 00000000000..ea756e0de94 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.txt @@ -0,0 +1,6 @@ +package test + +public open class StableName { + public constructor StableName() + public open fun connect(/*0*/ @kotlin.annotations.jvm.internal.ParameterName(value = "host") /* annotation class not found */ host: kotlin.String!): kotlin.Unit +} diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.java b/compiler/tests-common/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.java index c6836bb44af..dd6b8e8d2fa 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.java +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.ContentRootsKt; import org.jetbrains.kotlin.config.JVMConfigurationKeys; @@ -35,10 +36,7 @@ import org.jetbrains.kotlin.test.TestJdkKind; import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase; import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public abstract class KotlinMultiFileTestWithJava extends KtUsefulTestCase { protected File javaFilesDir; @@ -78,7 +76,7 @@ public abstract class KotlinMultiFileTestWithJava extends KtUsefulTestCase CompilerConfiguration configuration = KotlinTestUtils.newConfiguration( getConfigurationKind(), getTestJdkKind(file), - CollectionsKt.plus(Collections.singletonList(KotlinTestUtils.getAnnotationsJar()), getExtraClasspath()), + getClasspath(file), isJavaSourceRootNeeded() ? Collections.singletonList(javaFilesDir) : Collections.emptyList() ); configuration.add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, StandardScriptDefinition.INSTANCE); @@ -110,6 +108,22 @@ public abstract class KotlinMultiFileTestWithJava extends KtUsefulTestCase : TestJdkKind.MOCK_JDK; } + private List getClasspath(File file) { + List result = new ArrayList<>(); + result.add(KotlinTestUtils.getAnnotationsJar()); + result.addAll(getExtraClasspath()); + + boolean loadAndroidAnnotations = InTextDirectivesUtils.isDirectiveDefined( + FilesKt.readText(file, Charsets.UTF_8), "ANDROID_ANNOTATIONS" + ); + + if (loadAndroidAnnotations) { + result.add(ForTestCompileRuntime.androidAnnotationsForTests()); + } + + return result; + } + @NotNull protected List getExtraClasspath() { return Collections.emptyList(); diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java index 49a2f3c6463..9faf31f95f2 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; @@ -555,12 +556,21 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { @Nullable File javaSourceDir ) { configurationKind = extractConfigurationKind(files); + boolean loadAndroidAnnotations = files.stream().anyMatch(it -> + InTextDirectivesUtils.isDirectiveDefined(it.content, "ANDROID_ANNOTATIONS") + ); List javacOptions = extractJavacOptions(files); + List classpath = new ArrayList<>(); + classpath.add(getAnnotationsJar()); + + if (loadAndroidAnnotations) { + classpath.add(ForTestCompileRuntime.androidAnnotationsForTests()); + } CompilerConfiguration configuration = createConfiguration( configurationKind, getJdkKind(files), - Collections.singletonList(getAnnotationsJar()), + classpath, ArraysKt.filterNotNull(new File[] {javaSourceDir}), files ); @@ -586,8 +596,15 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { OutputUtilsKt.writeAllTo(classFileFactory, kotlinOut); + List javaClasspath = new ArrayList<>(); + javaClasspath.add(kotlinOut.getPath()); + + if (loadAndroidAnnotations) { + javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath()); + } + javaClassesOutputDirectory = CodegenTestUtil.compileJava( - findJavaSourcesInDirectory(javaSourceDir), Collections.singletonList(kotlinOut.getPath()), javacOptions + findJavaSourcesInDirectory(javaSourceDir), javaClasspath, javacOptions ); } } diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java index 98e2e6f4d3e..da1b9f9af2b 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/forTestCompile/ForTestCompileRuntime.java @@ -76,6 +76,11 @@ public class ForTestCompileRuntime { return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-jvm.jar")); } + @NotNull + public static File androidAnnotationsForTests() { + return assertExists(new File("dist/kotlinc/lib/android-annotations.jar")); + } + // TODO: Do not use these classes, remove them after stdlib tests are merged in the same build as the compiler @NotNull @Deprecated diff --git a/compiler/tests-common/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java b/compiler/tests-common/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java index 9978079443a..72e9d2ad428 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java +++ b/compiler/tests-common/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java @@ -19,7 +19,11 @@ package org.jetbrains.kotlin.jvm.compiler; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.text.StringKt; import kotlin.collections.CollectionsKt; +import kotlin.io.FilesKt; +import kotlin.sequences.SequencesKt; +import kotlin.text.Charsets; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; @@ -39,6 +43,7 @@ import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil; import org.jetbrains.kotlin.test.ConfigurationKind; +import org.jetbrains.kotlin.test.InTextDirectivesUtils; import org.jetbrains.kotlin.test.KotlinTestUtils; import org.jetbrains.kotlin.test.TestJdkKind; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; @@ -49,6 +54,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; public class LoadDescriptorUtil { @NotNull @@ -103,10 +109,21 @@ public class LoadDescriptorUtil { } public static void compileJavaWithAnnotationsJar(@NotNull Collection javaFiles, @NotNull File outDir) throws IOException { - String classPath = ForTestCompileRuntime.runtimeJarForTests() + File.pathSeparator + - KotlinTestUtils.getAnnotationsJar().getPath(); + List classpath = new ArrayList<>(); + + classpath.add(ForTestCompileRuntime.runtimeJarForTests()); + classpath.add(KotlinTestUtils.getAnnotationsJar()); + + for (File test: javaFiles) { + String content = FilesKt.readText(test, Charsets.UTF_8); + + if (InTextDirectivesUtils.isDirectiveDefined(content, "ANDROID_ANNOTATIONS")) { + classpath.add(ForTestCompileRuntime.androidAnnotationsForTests()); + } + } + KotlinTestUtils.compileJavaFiles(javaFiles, Arrays.asList( - "-classpath", classPath, + "-classpath", classpath.stream().map(File::getPath).collect(Collectors.joining(File.pathSeparator)), "-sourcepath", "compiler/testData/loadJava/include", "-d", outDir.getPath() )); diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 166c935de04..80fddf9ee69 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -18216,6 +18216,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("reorderedParameterNames.kt") + public void testReorderedParameterNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/smap") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index a6e9aee37d0..317edc170a2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13003,6 +13003,51 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractDiagnosticsTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("emptyParameterName.kt") + public void testEmptyParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("overridesParameterName.kt") + public void testOverridesParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("reorderedParameterNames.kt") + public void testReorderedParameterNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt"); + doTest(fileName); + } + + @TestMetadata("sameParameterName.kt") + public void testSameParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("specialCharsParameterName.kt") + public void testSpecialCharsParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("stableParameterName.kt") + public void testStableParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/specialBuiltIns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 0c124fa9d4c..dece136a297 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -13003,6 +13003,51 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing } } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractDiagnosticsUsingJavacTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("emptyParameterName.kt") + public void testEmptyParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("overridesParameterName.kt") + public void testOverridesParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("reorderedParameterNames.kt") + public void testReorderedParameterNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt"); + doTest(fileName); + } + + @TestMetadata("sameParameterName.kt") + public void testSameParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("specialCharsParameterName.kt") + public void testSpecialCharsParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt"); + doTest(fileName); + } + + @TestMetadata("stableParameterName.kt") + public void testStableParameterName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/j+k/specialBuiltIns") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3faebe099e0..3891f05cbea 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -18216,6 +18216,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("reorderedParameterNames.kt") + public void testReorderedParameterNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/smap") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6b209eec632..f701eac5501 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -18216,6 +18216,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractLightAnalysisModeTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("reorderedParameterNames.kt") + public void testReorderedParameterNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/smap") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 10c19e92a27..a6eaa69d7b7 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -1604,6 +1604,21 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { } } + @TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractLoadJavaTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("StableName.java") + public void testStableName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java"); + doTestCompiledJava(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaWithFastClassReadingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaWithFastClassReadingTestGenerated.java index 7a2ef1b8409..d323054228a 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaWithFastClassReadingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaWithFastClassReadingTestGenerated.java @@ -1602,6 +1602,21 @@ public class LoadJavaWithFastClassReadingTestGenerated extends AbstractLoadJavaW } } + @TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractLoadJavaWithFastClassReadingTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("StableName.java") + public void testStableName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java"); + doTestCompiledJava(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java index a33f22c3588..2791e402eff 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java @@ -1604,6 +1604,21 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT } } + @TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractLoadJavaUsingJavacTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("StableName.java") + public void testStableName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java"); + doTestCompiledJava(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index 0c188e4ee7a..b97fbbb0f56 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -4049,6 +4049,21 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD } } + @TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractJvmRuntimeDescriptorLoaderTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("StableName.java") + public void testStableName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index 480b3b91ccb..8ff42214bfd 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -51,6 +51,8 @@ public final class JvmAnnotationNames { public static final FqName ENHANCED_NULLABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedNullability"); public static final FqName ENHANCED_MUTABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedMutability"); + public static final FqName PARAMETER_NAME_FQ_NAME = new FqName("kotlin.annotations.jvm.internal.ParameterName"); + private JvmAnnotationNames() { } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt index 6e1553e8f92..0fdf25d8186 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/util.kt @@ -19,14 +19,18 @@ package org.jetbrains.kotlin.load.java.descriptors import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource +import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun copyValueParameters( newValueParametersTypes: Collection, @@ -71,3 +75,13 @@ fun DeserializedMemberDescriptor.getImplClassNameForDeserialized(): JvmClassName fun DeserializedMemberDescriptor.isFromJvmPackagePart(): Boolean = containerSource is JvmPackagePartSource + +fun ValueParameterDescriptor.getParameterNameAnnotation(): AnnotationDescriptor? { + val annotation = annotations.findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME) ?: return null + if (annotation.firstArgumentValue()?.safeAs()?.isEmpty() != false) { + return null + } + + return annotation +} + diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index 4b3633aa5d1..8fdaed9c316 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.components.TypeUsage import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor @@ -32,8 +33,10 @@ import org.jetbrains.kotlin.load.java.structure.JavaArrayType import org.jetbrains.kotlin.load.java.structure.JavaField import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.load.java.structure.JavaValueParameter +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.retainMostSpecificInEachOverridableGroup import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter @@ -45,6 +48,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.util.* abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberScopeImpl() { @@ -161,11 +165,16 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS jValueParameters: List ): ResolvedValueParameters { var synthesizedNames = false - val descriptors = jValueParameters.withIndex().map { pair -> - val (index, javaParameter) = pair + val usedNames = mutableSetOf() + val descriptors = jValueParameters.withIndex().map { (index, javaParameter) -> val annotations = c.resolveAnnotations(javaParameter) val typeUsage = TypeUsage.COMMON.toAttributes() + val parameterName = annotations + .findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME) + ?.firstArgumentValue() + ?.safeAs() + val (outType, varargElementType) = if (javaParameter.isVararg) { val paramType = javaParameter.type as? JavaArrayType @@ -186,6 +195,9 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS // TODO: fix Java parameter name loading logic somehow (don't always load "p0", "p1", etc.) Name.identifier("other") } + else if (parameterName != null && parameterName.isNotEmpty() && usedNames.add(parameterName)) { + Name.identifier(parameterName) + } else { // TODO: parameter names may be drawn from attached sources, which is slow; it's better to make them lazy val javaName = javaParameter.name diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index dbd3107e430..c5f27ecf099 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -21918,6 +21918,15 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/signatureAnnotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SignatureAnnotations extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + } + @TestMetadata("compiler/testData/codegen/box/smap") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/libraries/tools/android-annotations/build.gradle b/libraries/tools/android-annotations/build.gradle new file mode 100644 index 00000000000..17588afa83b --- /dev/null +++ b/libraries/tools/android-annotations/build.gradle @@ -0,0 +1,36 @@ +description = 'Kotlin annotations for Android' + +apply plugin: 'kotlin' + +configureJvm6Project(project) +configurePublishing(project) + +sourceSets { + main { + kotlin { + srcDir 'src' + } + } +} + +artifacts { + archives sourcesJar + archives javadocJar +} + +dist { + from (jar, sourcesJar) +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions.jdkHome = JDK_16 + kotlinOptions.jvmTarget = 1.6 +} + +compileKotlin { + kotlinOptions.freeCompilerArgs = [ + "-Xallow-kotlin-package", + "-module-name", project.name + ] +} + diff --git a/libraries/tools/android-annotations/src/kotlin/Annotations.kt b/libraries/tools/android-annotations/src/kotlin/Annotations.kt new file mode 100644 index 00000000000..10cabe9f569 --- /dev/null +++ b/libraries/tools/android-annotations/src/kotlin/Annotations.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.annotations.jvm.internal + +/** + * Defines parameter name. + */ +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.BINARY) +public annotation class ParameterName(val value: String) diff --git a/settings.gradle b/settings.gradle index f91b6cd22a5..4b4016cbe86 100644 --- a/settings.gradle +++ b/settings.gradle @@ -132,6 +132,7 @@ include ":kotlin-build-common", ":ultimate", ":ultimate:ultimate-runner", ":kotlin-annotations-jvm", + ":android-annotations", // plugin markers: ':kotlin-gradle-plugin:plugin-marker', @@ -201,6 +202,7 @@ project(':kotlin-annotation-processing').projectDir = "$rootDir/plugins/kapt3" a project(':examples:kotlin-jsr223-local-example').projectDir = "$rootDir/libraries/examples/kotlin-jsr223-local-example" as File project(':examples:kotlin-jsr223-daemon-local-eval-example').projectDir = "$rootDir/libraries/examples/kotlin-jsr223-daemon-local-eval-example" as File project(':kotlin-annotations-jvm').projectDir = "$rootDir/libraries/tools/kotlin-annotations-jvm" as File +project(':android-annotations').projectDir = "$rootDir/libraries/tools/android-annotations" as File // plugin markers: project(':kotlin-gradle-plugin:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-gradle-plugin/plugin-marker")