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
|
||||
) {
|
||||
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);
|
||||
this.calleeDescriptor = descriptor;
|
||||
|
||||
|
||||
+13
-1
@@ -32,6 +32,7 @@ import java.util.Collections;
|
||||
|
||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||
private final PropertyDescriptor calleeDescriptor;
|
||||
private final int accessorIndex;
|
||||
|
||||
public AccessorForPropertyDescriptor(@NotNull PropertyDescriptor pd, @NotNull DeclarationDescriptor containingDeclaration, int 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
|
||||
) {
|
||||
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);
|
||||
|
||||
this.calleeDescriptor = original;
|
||||
this.accessorIndex = index;
|
||||
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
||||
initialize(new Getter(this), new Setter(this));
|
||||
}
|
||||
@@ -89,4 +91,14 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
||||
public PropertyDescriptor getCalleeDescriptor() {
|
||||
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.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.psi.JetExpression;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
@@ -590,12 +591,16 @@ public class JetTypeMapper {
|
||||
return property.getName().asString();
|
||||
}
|
||||
|
||||
if (descriptor instanceof PropertyGetterDescriptor) {
|
||||
return PropertyCodegen.getterName(property.getName());
|
||||
}
|
||||
else {
|
||||
return PropertyCodegen.setterName(property.getName());
|
||||
}
|
||||
boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
|
||||
Name propertyName = isAccessor
|
||||
? Name.identifier(((AccessorForPropertyDescriptor) property).getIndexedAccessorSuffix())
|
||||
: property.getName();
|
||||
|
||||
String accessorName = descriptor instanceof PropertyGetterDescriptor
|
||||
? PropertyCodegen.getterName(propertyName)
|
||||
: PropertyCodegen.setterName(propertyName);
|
||||
|
||||
return isAccessor ? "access$" + accessorName : accessorName;
|
||||
}
|
||||
else if (isLocalNamedFun(descriptor)) {
|
||||
return "invoke";
|
||||
|
||||
@@ -23,7 +23,7 @@ class SubTr : Tr {
|
||||
// Clashing synthetic accessors are only reported in compiler, IDE doesn't see them
|
||||
class C {
|
||||
private fun f() {}
|
||||
fun `f$b$0`(c: C) {}
|
||||
fun `access$f$0`(c: C) {}
|
||||
|
||||
class Nested {
|
||||
|
||||
@@ -31,4 +31,4 @@ class C {
|
||||
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):
|
||||
fun getX(): 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):
|
||||
fun <get-tr>(): 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):
|
||||
fun `f$b$0`(c: C): kotlin.Unit
|
||||
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 `access$f$0`(c: C): 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):
|
||||
fun `f$b$0`(c: C): kotlin.Unit
|
||||
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 `access$f$0`(c: C): kotlin.Unit
|
||||
fun f(): kotlin.Unit
|
||||
COMPILATION_ERROR
|
||||
@@ -1,14 +1,14 @@
|
||||
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 `setBar$b$1`(d: Derived, i: Int) {}
|
||||
open fun `access$getBar$1`(d: Derived): Int = 1
|
||||
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() {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
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):
|
||||
fun `foo$b$0`(d: Derived): kotlin.Unit
|
||||
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 `access$foo$0`(d: Derived): 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):
|
||||
fun `getBar$b$1`(d: Derived): kotlin.Int
|
||||
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 `access$getBar$1`(d: Derived): 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):
|
||||
fun `setBar$b$1`(d: Derived, i: kotlin.Int): kotlin.Unit
|
||||
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 `access$setBar$1`(d: Derived, i: 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):
|
||||
fun `getBaz$b$2`(d: Derived): kotlin.Int
|
||||
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 `access$getBaz$2`(d: Derived): 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):
|
||||
fun `getBoo$b$3`(d: Derived): kotlin.Int
|
||||
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 `access$getBoo$3`(d: Derived): 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):
|
||||
fun `setBar1$b$4`(d: Derived, i: kotlin.Int): kotlin.Unit
|
||||
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 `access$setBar1$4`(d: Derived, i: kotlin.Int): kotlin.Unit
|
||||
fun <set-bar1>(<set-?>: kotlin.Int): kotlin.Unit
|
||||
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
|
||||
// 2 ALOAD 0
|
||||
// 1 synthetic getR
|
||||
// 1 synthetic access\$getR
|
||||
|
||||
@@ -96,7 +96,15 @@ public class MethodOrderTest: CodegenTestCase() {
|
||||
}
|
||||
""",
|
||||
"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.StoreStackBeforeInline.class,
|
||||
BlackBoxWithStdlibCodegenTestGenerated.Strings.class,
|
||||
BlackBoxWithStdlibCodegenTestGenerated.Synthetic.class,
|
||||
BlackBoxWithStdlibCodegenTestGenerated.ToArray.class,
|
||||
BlackBoxWithStdlibCodegenTestGenerated.Vararg.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")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user