Change synthetic accessor method names to "access$..."
As per discussion in https://youtrack.jetbrains.com/issue/KT-6870
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl
|
|||||||
int index
|
int index
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, null, Annotations.EMPTY,
|
super(containingDeclaration, null, Annotations.EMPTY,
|
||||||
Name.identifier((descriptor instanceof ConstructorDescriptor ? "$init" : descriptor.getName()) + "$b$" + index),
|
Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index),
|
||||||
Kind.DECLARATION, SourceElement.NO_SOURCE);
|
Kind.DECLARATION, SourceElement.NO_SOURCE);
|
||||||
this.calleeDescriptor = descriptor;
|
this.calleeDescriptor = descriptor;
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -32,6 +32,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||||
private final PropertyDescriptor calleeDescriptor;
|
private final PropertyDescriptor calleeDescriptor;
|
||||||
|
private final int accessorIndex;
|
||||||
|
|
||||||
public AccessorForPropertyDescriptor(@NotNull PropertyDescriptor pd, @NotNull DeclarationDescriptor containingDeclaration, int index) {
|
public AccessorForPropertyDescriptor(@NotNull PropertyDescriptor pd, @NotNull DeclarationDescriptor containingDeclaration, int index) {
|
||||||
this(pd, pd.getType(), DescriptorUtils.getReceiverParameterType(pd.getExtensionReceiverParameter()), pd.getDispatchReceiverParameter(), containingDeclaration, index);
|
this(pd, pd.getType(), DescriptorUtils.getReceiverParameterType(pd.getExtensionReceiverParameter()), pd.getDispatchReceiverParameter(), containingDeclaration, index);
|
||||||
@@ -46,10 +47,11 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
int index
|
int index
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, null, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL,
|
super(containingDeclaration, null, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL,
|
||||||
original.isVar(), Name.identifier(original.getName() + "$b$" + index),
|
original.isVar(), Name.identifier("access$" + getIndexedAccessorSuffix(original, index)),
|
||||||
Kind.DECLARATION, SourceElement.NO_SOURCE);
|
Kind.DECLARATION, SourceElement.NO_SOURCE);
|
||||||
|
|
||||||
this.calleeDescriptor = original;
|
this.calleeDescriptor = original;
|
||||||
|
this.accessorIndex = index;
|
||||||
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
||||||
initialize(new Getter(this), new Setter(this));
|
initialize(new Getter(this), new Setter(this));
|
||||||
}
|
}
|
||||||
@@ -89,4 +91,14 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
public PropertyDescriptor getCalleeDescriptor() {
|
public PropertyDescriptor getCalleeDescriptor() {
|
||||||
return calleeDescriptor;
|
return calleeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getIndexedAccessorSuffix() {
|
||||||
|
return getIndexedAccessorSuffix(calleeDescriptor, accessorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static String getIndexedAccessorSuffix(@NotNull PropertyDescriptor original, int index) {
|
||||||
|
return original.getName() + "$" + index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
|||||||
import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
|
import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||||
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.name.SpecialNames;
|
import org.jetbrains.kotlin.name.SpecialNames;
|
||||||
import org.jetbrains.kotlin.psi.JetExpression;
|
import org.jetbrains.kotlin.psi.JetExpression;
|
||||||
import org.jetbrains.kotlin.psi.JetFile;
|
import org.jetbrains.kotlin.psi.JetFile;
|
||||||
@@ -590,12 +591,16 @@ public class JetTypeMapper {
|
|||||||
return property.getName().asString();
|
return property.getName().asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof PropertyGetterDescriptor) {
|
boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
|
||||||
return PropertyCodegen.getterName(property.getName());
|
Name propertyName = isAccessor
|
||||||
}
|
? Name.identifier(((AccessorForPropertyDescriptor) property).getIndexedAccessorSuffix())
|
||||||
else {
|
: property.getName();
|
||||||
return PropertyCodegen.setterName(property.getName());
|
|
||||||
}
|
String accessorName = descriptor instanceof PropertyGetterDescriptor
|
||||||
|
? PropertyCodegen.getterName(propertyName)
|
||||||
|
: PropertyCodegen.setterName(propertyName);
|
||||||
|
|
||||||
|
return isAccessor ? "access$" + accessorName : accessorName;
|
||||||
}
|
}
|
||||||
else if (isLocalNamedFun(descriptor)) {
|
else if (isLocalNamedFun(descriptor)) {
|
||||||
return "invoke";
|
return "invoke";
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SubTr : Tr {
|
|||||||
// Clashing synthetic accessors are only reported in compiler, IDE doesn't see them
|
// Clashing synthetic accessors are only reported in compiler, IDE doesn't see them
|
||||||
class C {
|
class C {
|
||||||
private fun f() {}
|
private fun f() {}
|
||||||
fun `f$b$0`(c: C) {}
|
fun `access$f$0`(c: C) {}
|
||||||
|
|
||||||
class Nested {
|
class Nested {
|
||||||
|
|
||||||
@@ -31,4 +31,4 @@ class C {
|
|||||||
C().f()
|
C().f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
WARNING: compiler/testData/cli/jvm/signatureClash.kt: (26, 17) Parameter 'c' is never used
|
WARNING: compiler/testData/cli/jvm/signatureClash.kt: (26, 22) Parameter 'c' is never used
|
||||||
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (6, 5) Accidental override: The following declarations have the same JVM signature (getX()I):
|
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (6, 5) Accidental override: The following declarations have the same JVM signature (getX()I):
|
||||||
fun getX(): kotlin.Int
|
fun getX(): kotlin.Int
|
||||||
fun <get-x>(): kotlin.Int
|
fun <get-x>(): kotlin.Int
|
||||||
@@ -20,10 +20,10 @@ ERROR: compiler/testData/cli/jvm/signatureClash.kt: (19, 7) Platform declaration
|
|||||||
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (20, 5) Platform declaration clash: The following declarations have the same JVM signature (getTr()I):
|
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (20, 5) Platform declaration clash: The following declarations have the same JVM signature (getTr()I):
|
||||||
fun <get-tr>(): kotlin.Int
|
fun <get-tr>(): kotlin.Int
|
||||||
fun getTr(): kotlin.Int
|
fun getTr(): kotlin.Int
|
||||||
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (24, 7) Platform declaration clash: The following declarations have the same JVM signature (f$b$0(LC;)V):
|
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (24, 7) Platform declaration clash: The following declarations have the same JVM signature (access$f$0(LC;)V):
|
||||||
fun `f$b$0`(c: C): kotlin.Unit
|
fun `access$f$0`(c: C): kotlin.Unit
|
||||||
fun f(): kotlin.Unit
|
fun f(): kotlin.Unit
|
||||||
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (26, 5) Platform declaration clash: The following declarations have the same JVM signature (f$b$0(LC;)V):
|
ERROR: compiler/testData/cli/jvm/signatureClash.kt: (26, 5) Platform declaration clash: The following declarations have the same JVM signature (access$f$0(LC;)V):
|
||||||
fun `f$b$0`(c: C): kotlin.Unit
|
fun `access$f$0`(c: C): kotlin.Unit
|
||||||
fun f(): kotlin.Unit
|
fun f(): kotlin.Unit
|
||||||
COMPILATION_ERROR
|
COMPILATION_ERROR
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
open class Base {
|
open class Base {
|
||||||
open fun `foo$b$0`(d: Derived) {}
|
open fun `access$foo$0`(d: Derived) {}
|
||||||
|
|
||||||
open fun `getBar$b$1`(d: Derived): Int = 1
|
open fun `access$getBar$1`(d: Derived): Int = 1
|
||||||
open fun `setBar$b$1`(d: Derived, i: Int) {}
|
open fun `access$setBar$1`(d: Derived, i: Int) {}
|
||||||
|
|
||||||
open fun `getBaz$b$2`(d: Derived): Int = 1
|
open fun `access$getBaz$2`(d: Derived): Int = 1
|
||||||
|
|
||||||
open fun `getBoo$b$3`(d: Derived): Int = 1
|
open fun `access$getBoo$3`(d: Derived): Int = 1
|
||||||
|
|
||||||
open fun `setBar1$b$4`(d: Derived, i: Int) {}
|
open fun `access$setBar1$4`(d: Derived, i: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Derived : Base() {
|
class Derived : Base() {
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
WARNING: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (34, 17) Variable 's' is never used
|
WARNING: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (34, 17) Variable 's' is never used
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (15, 5) Accidental override: The following declarations have the same JVM signature (foo$b$0(LDerived;)V):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (15, 5) Accidental override: The following declarations have the same JVM signature (access$foo$0(LDerived;)V):
|
||||||
fun `foo$b$0`(d: Derived): kotlin.Unit
|
fun `access$foo$0`(d: Derived): kotlin.Unit
|
||||||
fun foo(): kotlin.Unit
|
fun foo(): kotlin.Unit
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (18, 9) Accidental override: The following declarations have the same JVM signature (getBar$b$1(LDerived;)I):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (18, 9) Accidental override: The following declarations have the same JVM signature (access$getBar$1(LDerived;)I):
|
||||||
fun `getBar$b$1`(d: Derived): kotlin.Int
|
fun `access$getBar$1`(d: Derived): kotlin.Int
|
||||||
fun <get-bar>(): kotlin.Int
|
fun <get-bar>(): kotlin.Int
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (19, 9) Accidental override: The following declarations have the same JVM signature (setBar$b$1(LDerived;I)V):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (19, 9) Accidental override: The following declarations have the same JVM signature (access$setBar$1(LDerived;I)V):
|
||||||
fun `setBar$b$1`(d: Derived, i: kotlin.Int): kotlin.Unit
|
fun `access$setBar$1`(d: Derived, i: kotlin.Int): kotlin.Unit
|
||||||
fun <set-bar>(<set-?>: kotlin.Int): kotlin.Unit
|
fun <set-bar>(<set-?>: kotlin.Int): kotlin.Unit
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (21, 5) Accidental override: The following declarations have the same JVM signature (getBaz$b$2(LDerived;)I):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (21, 5) Accidental override: The following declarations have the same JVM signature (access$getBaz$2(LDerived;)I):
|
||||||
fun `getBaz$b$2`(d: Derived): kotlin.Int
|
fun `access$getBaz$2`(d: Derived): kotlin.Int
|
||||||
fun <get-baz>(): kotlin.Int
|
fun <get-baz>(): kotlin.Int
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (23, 5) Accidental override: The following declarations have the same JVM signature (getBoo$b$3(LDerived;)I):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (23, 5) Accidental override: The following declarations have the same JVM signature (access$getBoo$3(LDerived;)I):
|
||||||
fun `getBoo$b$3`(d: Derived): kotlin.Int
|
fun `access$getBoo$3`(d: Derived): kotlin.Int
|
||||||
fun <get-boo>(): kotlin.Int
|
fun <get-boo>(): kotlin.Int
|
||||||
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (27, 9) Accidental override: The following declarations have the same JVM signature (setBar1$b$4(LDerived;I)V):
|
ERROR: compiler/testData/cli/jvm/syntheticAccessorSignatureClash.kt: (27, 9) Accidental override: The following declarations have the same JVM signature (access$setBar1$4(LDerived;I)V):
|
||||||
fun `setBar1$b$4`(d: Derived, i: kotlin.Int): kotlin.Unit
|
fun `access$setBar1$4`(d: Derived, i: kotlin.Int): kotlin.Unit
|
||||||
fun <set-bar1>(<set-?>: kotlin.Int): kotlin.Unit
|
fun <set-bar1>(<set-?>: kotlin.Int): kotlin.Unit
|
||||||
COMPILATION_ERROR
|
COMPILATION_ERROR
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// This test checks that synthetic accessors generated by Kotlin compiler have names starting with "access$"
|
||||||
|
// This is crucial for some JVM frameworks like Quasar which rely on the bytecode being similar to the one generated by javac
|
||||||
|
// See https://youtrack.jetbrains.com/issue/KT-6870
|
||||||
|
|
||||||
|
class PrivateConstructor private() {
|
||||||
|
class Nested { val a = PrivateConstructor() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrivatePropertyGet {
|
||||||
|
private val x = 42
|
||||||
|
|
||||||
|
inner class Inner { val a = x }
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrivatePropertySet {
|
||||||
|
private var x = "a"
|
||||||
|
|
||||||
|
inner class Inner { { x = "b" } }
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrivateMethod {
|
||||||
|
private fun foo() = ""
|
||||||
|
|
||||||
|
inner class Inner { val a = foo() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun check(klass: Class<*>) {
|
||||||
|
for (method in klass.getDeclaredMethods()) {
|
||||||
|
if (method.isSynthetic() && method.getName().startsWith("access$")) return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw AssertionError("No synthetic methods starting with 'access$' found in class $klass")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
check(javaClass<PrivateConstructor>())
|
||||||
|
check(javaClass<PrivatePropertyGet>())
|
||||||
|
check(javaClass<PrivatePropertySet>())
|
||||||
|
check(javaClass<PrivateMethod>())
|
||||||
|
|
||||||
|
// Also check that synthetic accessors really work
|
||||||
|
PrivateConstructor.Nested()
|
||||||
|
PrivatePropertyGet().Inner()
|
||||||
|
PrivatePropertySet().Inner()
|
||||||
|
PrivateMethod().Inner()
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -5,4 +5,4 @@ class A {
|
|||||||
}
|
}
|
||||||
// A and class object constructor call
|
// A and class object constructor call
|
||||||
// 2 ALOAD 0
|
// 2 ALOAD 0
|
||||||
// 1 synthetic getR
|
// 1 synthetic access\$getR
|
||||||
|
|||||||
@@ -96,7 +96,15 @@ public class MethodOrderTest: CodegenTestCase() {
|
|||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
"Outer",
|
"Outer",
|
||||||
listOf("<clinit>()V", "c()V", "<init>(ILjava/lang/String;)V", "getB\$b$0(LOuter;)Ljava/lang/String;", "setB\$b$0(LOuter;Ljava/lang/String;)V", "getA\$b$1(LOuter;)I", "c\$b$2(LOuter;)V")
|
listOf(
|
||||||
|
"<clinit>()V",
|
||||||
|
"c()V",
|
||||||
|
"<init>(ILjava/lang/String;)V",
|
||||||
|
"access\$getB$0(LOuter;)Ljava/lang/String;",
|
||||||
|
"access\$setB$0(LOuter;Ljava/lang/String;)V",
|
||||||
|
"access\$getA$1(LOuter;)I",
|
||||||
|
"access\$c$2(LOuter;)V"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
@@ -60,6 +60,7 @@ import java.util.regex.Pattern;
|
|||||||
BlackBoxWithStdlibCodegenTestGenerated.Reified.class,
|
BlackBoxWithStdlibCodegenTestGenerated.Reified.class,
|
||||||
BlackBoxWithStdlibCodegenTestGenerated.StoreStackBeforeInline.class,
|
BlackBoxWithStdlibCodegenTestGenerated.StoreStackBeforeInline.class,
|
||||||
BlackBoxWithStdlibCodegenTestGenerated.Strings.class,
|
BlackBoxWithStdlibCodegenTestGenerated.Strings.class,
|
||||||
|
BlackBoxWithStdlibCodegenTestGenerated.Synthetic.class,
|
||||||
BlackBoxWithStdlibCodegenTestGenerated.ToArray.class,
|
BlackBoxWithStdlibCodegenTestGenerated.ToArray.class,
|
||||||
BlackBoxWithStdlibCodegenTestGenerated.Vararg.class,
|
BlackBoxWithStdlibCodegenTestGenerated.Vararg.class,
|
||||||
BlackBoxWithStdlibCodegenTestGenerated.When.class,
|
BlackBoxWithStdlibCodegenTestGenerated.When.class,
|
||||||
@@ -3201,6 +3202,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/synthetic")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Synthetic extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInSynthetic() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/synthetic"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("syntheticAccessorNames.kt")
|
||||||
|
public void testSyntheticAccessorNames() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/synthetic/syntheticAccessorNames.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/toArray")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/toArray")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user