Merge "Add test for object and global Kotlin properties"
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
index cb3820e..73d70e1 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
@@ -57,6 +57,28 @@
.addProperty("internalLateInitProp", JAVA_LANG_STRING, Visibility.INTERNAL)
.addProperty("publicLateInitProp", JAVA_LANG_STRING, Visibility.PUBLIC);
+ private static final TestKotlinClass OBJECT_PROPERTY_CLASS =
+ new TestKotlinClass("properties.ObjectProperties")
+ .addProperty("privateProp", JAVA_LANG_STRING, Visibility.PRIVATE)
+ .addProperty("protectedProp", JAVA_LANG_STRING, Visibility.PROTECTED)
+ .addProperty("internalProp", JAVA_LANG_STRING, Visibility.INTERNAL)
+ .addProperty("publicProp", JAVA_LANG_STRING, Visibility.PUBLIC)
+ .addProperty("primitiveProp", "int", Visibility.PUBLIC)
+ .addProperty("privateLateInitProp", JAVA_LANG_STRING, Visibility.PRIVATE)
+ .addProperty("internalLateInitProp", JAVA_LANG_STRING, Visibility.INTERNAL)
+ .addProperty("publicLateInitProp", JAVA_LANG_STRING, Visibility.PUBLIC);
+
+ private static final TestFileLevelKotlinClass FILE_PROPERTY_CLASS =
+ new TestFileLevelKotlinClass("properties.FilePropertiesKt")
+ .addProperty("privateProp", JAVA_LANG_STRING, Visibility.PRIVATE)
+ .addProperty("protectedProp", JAVA_LANG_STRING, Visibility.PROTECTED)
+ .addProperty("internalProp", JAVA_LANG_STRING, Visibility.INTERNAL)
+ .addProperty("publicProp", JAVA_LANG_STRING, Visibility.PUBLIC)
+ .addProperty("primitiveProp", "int", Visibility.PUBLIC)
+ .addProperty("privateLateInitProp", JAVA_LANG_STRING, Visibility.PRIVATE)
+ .addProperty("internalLateInitProp", JAVA_LANG_STRING, Visibility.INTERNAL)
+ .addProperty("publicLateInitProp", JAVA_LANG_STRING, Visibility.PUBLIC);
+
@Test
public void testMutableProperty_getterAndSetterAreRemoveIfNotUsed() throws Exception {
String mainClass = addMainToClasspath("properties/MutablePropertyKt",
@@ -537,4 +559,363 @@
assertTrue(fieldSubject.getField().accessFlags.isPublic());
});
}
+
+ @Test
+ public void testObjectClass_primitivePropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_usePrimitiveProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "primitiveProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, "int", propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined when we don't know if null check semantic is
+ // preserved.
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testObjectClass_privatePropertyIsAlwaysInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_usePrivateProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "privateProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // A private property has no getter/setter.
+ checkMethodIsAbsent(objectClass, getter);
+ checkMethodIsAbsent(objectClass, setter);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testObjectClass_internalPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_useInternalProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "internalProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined when we don't know if null check semantic is
+ // preserved.
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testObjectClass_publicPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_usePublicProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "publicProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined when we don't know if null check semantic is
+ // preserved.
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testObjectClass_privateLateInitPropertyIsAlwaysInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_useLateInitPrivateProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "privateLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // A private property has no getter/setter.
+ checkMethodIsAbsent(objectClass, getter);
+ checkMethodIsAbsent(objectClass, setter);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testObjectClass_internalLateInitPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_useLateInitInternalProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "internalLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined when we don't know if null check semantic is
+ // preserved.
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ });
+ }
+
+ @Test
+ public void testObjectClass_publicLateInitPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = OBJECT_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.ObjectPropertiesKt", "objectProperties_useLateInitPublicProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "publicLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined when we don't know if null check semantic is
+ // preserved.
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ });
+ }
+
+ @Test
+ public void testFileLevel_primitivePropertyIsInlinedIfAccessIsRelaxed() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_usePrimitiveProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "primitiveProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, "int", propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ checkMethodIsAbsent(objectClass, getter);
+ checkMethodIsAbsent(objectClass, setter);
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ checkMethodIsPresent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ }
+ });
+ }
+
+ @Test
+ public void testFileLevel_privatePropertyIsAlwaysInlined() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_usePrivateProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "privateProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // A private property has no getter/setter.
+ checkMethodIsAbsent(objectClass, getter);
+ checkMethodIsAbsent(objectClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testFileLevel_internalPropertyGetterIsInlinedIfAccessIsRelaxed() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_useInternalProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "internalProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+ // Note: the setter is considered as a regular method (because of KotlinC adding extra null
+ // checks), thus we cannot say if the setter would be inlined or not by R8.
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ checkMethodIsAbsent(objectClass, getter);
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ checkMethodIsPresent(objectClass, getter);
+ }
+ });
+ }
+
+ @Test
+ public void testFileLevel_publicPropertyGetterIsInlinedIfAccessIsRelaxed() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_usePublicProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "publicProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+ // On the other hand, the setter is considered as a regular method (because of null checks),
+ // thus we cannot say if it can be inlined or not.
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ checkMethodIsAbsent(objectClass, getter);
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ checkMethodIsPresent(objectClass, getter);
+ }
+ });
+ }
+
+ @Test
+ public void testFileLevel_privateLateInitPropertyIsAlwaysInlined() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_useLateInitPrivateProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject fileClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "privateLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(fileClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // A private property has no getter/setter.
+ checkMethodIsAbsent(fileClass, getter);
+ checkMethodIsAbsent(fileClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
+ }
+
+ @Test
+ public void testFileLevel_internalLateInitPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_useLateInitInternalProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "internalLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Field is public and getter is small so we expect to always inline it.
+ checkMethodIsAbsent(objectClass, getter);
+
+ // Setter has null check of new value, thus may not be inlined.
+ checkMethodIsPresent(objectClass, setter);
+ });
+ }
+
+ @Test
+ public void testFileLevel_publicLateInitPropertyCannotBeInlined() throws Exception {
+ final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
+ String mainClass = addMainToClasspath(
+ "properties.FilePropertiesKt", "fileProperties_useLateInitPublicProp");
+ runTest(PACKAGE_NAME, mainClass, (app) -> {
+ DexInspector dexInspector = new DexInspector(app);
+ ClassSubject objectClass = checkClassExists(dexInspector, testedClass.getClassName());
+ String propertyName = "publicLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsPresent(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ checkMethodIsAbsent(objectClass, getter);
+ checkMethodIsPresent(objectClass, setter);
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ });
+ }
+
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/TestFileLevelKotlinClass.java b/src/test/java/com/android/tools/r8/kotlin/TestFileLevelKotlinClass.java
new file mode 100644
index 0000000..db35897
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/TestFileLevelKotlinClass.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.kotlin;
+
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+
+public class TestFileLevelKotlinClass extends TestKotlinClass {
+
+ public TestFileLevelKotlinClass(String className) {
+ super(className);
+ }
+
+ @Override
+ public TestFileLevelKotlinClass addProperty(String name, String type, Visibility visibility) {
+ return (TestFileLevelKotlinClass) super.addProperty(name, type, visibility);
+ }
+
+ @Override
+ public MethodSignature getGetterForProperty(String propertyName) {
+ KotlinProperty property = getProperty(propertyName);
+ // File-level properties accessor do not apply mangling.
+ return getGetterForProperty(property, false);
+ }
+
+ @Override
+ public MethodSignature getSetterForProperty(String propertyName) {
+ KotlinProperty property = getProperty(propertyName);
+ // File-level properties accessor do not apply mangling.
+ return getSetterForProperty(property, false);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/TestKotlinClass.java b/src/test/java/com/android/tools/r8/kotlin/TestKotlinClass.java
index 0ec0f64..685df6a 100644
--- a/src/test/java/com/android/tools/r8/kotlin/TestKotlinClass.java
+++ b/src/test/java/com/android/tools/r8/kotlin/TestKotlinClass.java
@@ -104,22 +104,12 @@
public MemberNaming.MethodSignature getGetterForProperty(String propertyName) {
KotlinProperty property = getProperty(propertyName);
- String type = property.type;
- String getterName = computeGetterName(propertyName);
- if (property.getVisibility() == Visibility.INTERNAL) {
- getterName = appendInternalSuffix(getterName);
- }
- return new MemberNaming.MethodSignature(getterName, type, Collections.emptyList());
+ return getGetterForProperty(property, property.getVisibility() == Visibility.INTERNAL);
}
public MemberNaming.MethodSignature getSetterForProperty(String propertyName) {
KotlinProperty property = getProperty(propertyName);
- String setterName = computeSetterName(propertyName);
- if (property.getVisibility() == Visibility.INTERNAL) {
- setterName = appendInternalSuffix(setterName);
- }
- return new MemberNaming.MethodSignature(setterName, "void",
- Collections.singleton(property.getType()));
+ return getSetterForProperty(property, property.getVisibility() == Visibility.INTERNAL);
}
public MemberNaming.MethodSignature getGetterAccessorForProperty(String propertyName,
@@ -152,6 +142,26 @@
return new MemberNaming.MethodSignature(setterName, "void", argumentTypes);
}
+ protected final MemberNaming.MethodSignature getGetterForProperty(KotlinProperty property,
+ boolean applyMangling) {
+ String type = property.type;
+ String getterName = computeGetterName(property.name);
+ if (applyMangling) {
+ getterName = appendInternalSuffix(getterName);
+ }
+ return new MemberNaming.MethodSignature(getterName, type, Collections.emptyList());
+ }
+
+ protected final MemberNaming.MethodSignature getSetterForProperty(KotlinProperty property,
+ boolean applyMangling) {
+ String setterName = computeSetterName(property.name);
+ if (applyMangling) {
+ setterName = appendInternalSuffix(setterName);
+ }
+ return new MemberNaming.MethodSignature(setterName, "void",
+ Collections.singleton(property.getType()));
+ }
+
private static String computeGetterName(String propertyName) {
if (propertyName.length() > 2 && propertyName.startsWith("is")
&& (propertyName.charAt(2) == '_' || Character.isUpperCase(propertyName.charAt(2)))) {
diff --git a/src/test/kotlinR8TestResources/properties/FileProperties.kt b/src/test/kotlinR8TestResources/properties/FileProperties.kt
new file mode 100644
index 0000000..4671189
--- /dev/null
+++ b/src/test/kotlinR8TestResources/properties/FileProperties.kt
@@ -0,0 +1,82 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package properties
+
+private var privateProp: String = "privateProp"
+internal var internalProp: String = "internalProp"
+public var publicProp: String = "publicProp"
+
+private lateinit var privateLateInitProp: String
+internal lateinit var internalLateInitProp: String
+public lateinit var publicLateInitProp: String
+
+public var primitiveProp: Int = Int.MAX_VALUE
+
+// Serves as intermediate to make sure the access to a property is done from a separate class.
+private object Intermediate {
+ fun readPrivateProp() = privateProp
+ fun writePrivateProp(s: String) { privateProp = s }
+
+ fun readInternalProp() = internalProp
+ fun writeInternalProp(s: String) { internalProp = s }
+
+ fun readPublicProp() = publicProp
+ fun writePublicProp(s: String) { publicProp = s }
+
+ fun readPrimitiveProp() = primitiveProp
+ fun writePrimitiveProp(i: Int) { primitiveProp = i }
+
+ fun readLateInitPrivateProp() = privateLateInitProp
+ fun writeLateInitPrivateProp(s: String) { privateLateInitProp = s }
+
+ fun readLateInitInternalProp() = internalLateInitProp
+ fun writeLateInitInternalProp(s: String) { internalLateInitProp = s }
+
+ fun readLateInitPublicProp() = publicLateInitProp
+ fun writeLateInitPublicProp(s: String) { publicLateInitProp = s }
+}
+
+fun doNotUseProperties(): String {
+ return "doNotUseProperties"
+}
+
+fun fileProperties_noUseOfProperties() {
+ println(ObjectProperties.doNotUseProperties())
+}
+
+fun fileProperties_usePrivateProp() {
+ Intermediate.writePrivateProp("foo")
+ println(Intermediate.readPrivateProp())
+}
+
+fun fileProperties_useInternalProp() {
+ Intermediate.writeInternalProp("foo")
+ println(Intermediate.readInternalProp())
+}
+
+fun fileProperties_usePublicProp() {
+ Intermediate.writePublicProp("foo")
+ println(Intermediate.readPublicProp())
+}
+
+fun fileProperties_usePrimitiveProp() {
+ Intermediate.writePrimitiveProp(Int.MIN_VALUE)
+ println(Intermediate.readPrimitiveProp())
+}
+
+fun fileProperties_useLateInitPrivateProp() {
+ Intermediate.writeLateInitPrivateProp("foo")
+ println(Intermediate.readLateInitPrivateProp())
+}
+
+fun fileProperties_useLateInitInternalProp() {
+ Intermediate.writeLateInitInternalProp( "foo")
+ println(Intermediate.readLateInitInternalProp())
+}
+
+fun fileProperties_useLateInitPublicProp() {
+ Intermediate.writeLateInitPublicProp("foo")
+ println(Intermediate.readLateInitPublicProp())
+}
diff --git a/src/test/kotlinR8TestResources/properties/ObjectProperties.kt b/src/test/kotlinR8TestResources/properties/ObjectProperties.kt
new file mode 100644
index 0000000..d05e2a6
--- /dev/null
+++ b/src/test/kotlinR8TestResources/properties/ObjectProperties.kt
@@ -0,0 +1,76 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package properties
+
+object ObjectProperties {
+ private var privateProp: String = "privateProp"
+ internal var internalProp: String = "internalProp"
+ public var publicProp: String = "publicProp"
+
+ private lateinit var privateLateInitProp: String
+ internal lateinit var internalLateInitProp: String
+ public lateinit var publicLateInitProp: String
+
+ public var primitiveProp: Int = Int.MAX_VALUE
+
+ fun callSetterPrivateProp(v: String) {
+ privateProp = v
+ }
+
+ fun callGetterPrivateProp(): String {
+ return privateProp
+ }
+
+ fun callSetterLateInitPrivateProp(v: String) {
+ privateLateInitProp = v
+ }
+
+ fun callGetterLateInitPrivateProp(): String {
+ return privateLateInitProp
+ }
+
+ fun doNotUseProperties(): String {
+ return "doNotUseProperties"
+ }
+}
+
+fun objectProperties_noUseOfProperties() {
+ println(ObjectProperties.doNotUseProperties())
+}
+
+fun objectProperties_usePrivateProp() {
+ ObjectProperties.callSetterPrivateProp("foo")
+ println(ObjectProperties.callGetterPrivateProp())
+}
+
+fun objectProperties_useInternalProp() {
+ ObjectProperties.internalProp = "foo"
+ println(ObjectProperties.internalProp)
+}
+
+fun objectProperties_usePublicProp() {
+ ObjectProperties.publicProp = "foo"
+ println(ObjectProperties.publicProp)
+}
+
+fun objectProperties_usePrimitiveProp() {
+ ObjectProperties.primitiveProp = Int.MIN_VALUE
+ println(ObjectProperties.primitiveProp)
+}
+
+fun objectProperties_useLateInitPrivateProp() {
+ ObjectProperties.callSetterLateInitPrivateProp("foo")
+ println(ObjectProperties.callGetterLateInitPrivateProp())
+}
+
+fun objectProperties_useLateInitInternalProp() {
+ ObjectProperties.internalLateInitProp = "foo"
+ println(ObjectProperties.internalLateInitProp)
+}
+
+fun objectProperties_useLateInitPublicProp() {
+ ObjectProperties.publicLateInitProp = "foo"
+ println(ObjectProperties.publicLateInitProp)
+}