Change synthetic accessor method names to "access$..."

As per discussion in https://youtrack.jetbrains.com/issue/KT-6870
This commit is contained in:
Alexander Udalov
2015-02-27 16:18:03 +03:00
parent ac9e6cd9ca
commit 2c0830b017
11 changed files with 124 additions and 35 deletions
@@ -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;
@@ -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";
+2 -2
View File
@@ -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()
}
}
}
}
+5 -5
View File
@@ -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"
)
)
}
@@ -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)