Synthetic properties: correct behaviour for method hierarchies
This commit is contained in:
+54
-28
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.types.JetType
|
|||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeFirstWord
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeFirstWord
|
||||||
@@ -54,8 +55,7 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
|||||||
val identifier = name.getIdentifier()
|
val identifier = name.getIdentifier()
|
||||||
if (!identifier.startsWith("get") && !identifier.startsWith("is") && !identifier.startsWith("set")) return null // optimization
|
if (!identifier.startsWith("get") && !identifier.startsWith("is") && !identifier.startsWith("set")) return null // optimization
|
||||||
|
|
||||||
val owner = getterOrSetter.getContainingDeclaration()
|
val owner = getterOrSetter.getContainingDeclaration() as? ClassDescriptor ?: return null
|
||||||
if (owner !is JavaClassDescriptor) return null
|
|
||||||
|
|
||||||
val originalGetterOrSetter = getterOrSetter.original
|
val originalGetterOrSetter = getterOrSetter.original
|
||||||
return resolutionScope.getSyntheticExtensionProperties(listOf(owner.getDefaultType()))
|
return resolutionScope.getSyntheticExtensionProperties(listOf(owner.getDefaultType()))
|
||||||
@@ -94,50 +94,76 @@ class AdditionalScopesWithJavaSyntheticExtensions(storageManager: StorageManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
||||||
private val syntheticPropertyInClass = storageManager.createMemoizedFunctionWithNullableValues<Pair<JavaClassDescriptor, Name>, PropertyDescriptor> { pair ->
|
private val syntheticPropertyInClass = storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassDescriptor, Name>, PropertyDescriptor> { pair ->
|
||||||
syntheticPropertyInClassNotCached(pair.first, pair.second)
|
syntheticPropertyInClassNotCached(pair.first, pair.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syntheticPropertyInClassNotCached(javaClass: JavaClassDescriptor, name: Name): PropertyDescriptor? {
|
private fun syntheticPropertyInClassNotCached(ownerClass: ClassDescriptor, name: Name): PropertyDescriptor? {
|
||||||
if (name.isSpecial()) return null
|
if (name.isSpecial()) return null
|
||||||
val identifier = name.identifier
|
val identifier = name.identifier
|
||||||
if (identifier.isEmpty()) return null
|
if (identifier.isEmpty()) return null
|
||||||
val firstChar = identifier[0]
|
val firstChar = identifier[0]
|
||||||
if (!firstChar.isJavaIdentifierStart() || firstChar.isUpperCase()) return null
|
if (!firstChar.isJavaIdentifierStart() || firstChar.isUpperCase()) return null
|
||||||
|
|
||||||
val memberScope = javaClass.getUnsubstitutedMemberScope()
|
val memberScope = ownerClass.unsubstitutedMemberScope
|
||||||
val getMethod = possibleGetMethodNames(name)
|
val getMethod = possibleGetMethodNames(name)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.flatMap { memberScope.getFunctions(it).asSequence() }
|
.flatMap { memberScope.getFunctions(it).asSequence() }
|
||||||
.singleOrNull { it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && isGoodGetMethod(it) } ?: return null
|
.singleOrNull {
|
||||||
|
it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && isGoodGetMethod(it) && it.hasJavaOriginInHierarchy()
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
// don't accept "uRL" for "getURL" etc
|
// don't accept "uRL" for "getURL" etc
|
||||||
if (SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(getMethod.name) != name) return null
|
if (SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(getMethod.name) != name) return null
|
||||||
|
|
||||||
val propertyType = getMethod.getReturnType() ?: return null
|
val setMethod = memberScope.getFunctions(setMethodName(getMethod.name))
|
||||||
val setMethod = memberScope.getFunctions(setMethodName(getMethod.getName()))
|
.singleOrNull { isGoodSetMethod(it, getMethod) }
|
||||||
.singleOrNull { it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && isGoodSetMethod(it, propertyType) }
|
|
||||||
|
|
||||||
return MyPropertyDescriptor(javaClass, getMethod.original, setMethod?.original, name, propertyType)
|
val propertyType = getMethod.returnType ?: return null
|
||||||
|
return MyPropertyDescriptor(ownerClass, getMethod.original, setMethod?.original, name, propertyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
|
||||||
|
return if (overriddenDescriptors.isEmpty())
|
||||||
|
containingDeclaration is JavaClassDescriptor
|
||||||
|
else
|
||||||
|
overriddenDescriptors.any { it.hasJavaOriginInHierarchy() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isGoodGetMethod(descriptor: FunctionDescriptor): Boolean {
|
private fun isGoodGetMethod(descriptor: FunctionDescriptor): Boolean {
|
||||||
val returnType = descriptor.getReturnType() ?: return false
|
val returnType = descriptor.returnType ?: return false
|
||||||
if (returnType.isUnit()) return false
|
if (returnType.isUnit()) return false
|
||||||
if (descriptor.getName().asString().startsWith("is") && !returnType.isBoolean()) return false
|
if (descriptor.name.asString().startsWith("is") && !returnType.isBoolean()) return false
|
||||||
|
|
||||||
return descriptor.getValueParameters().isEmpty()
|
return descriptor.valueParameters.isEmpty()
|
||||||
&& descriptor.getTypeParameters().isEmpty()
|
&& descriptor.typeParameters.isEmpty()
|
||||||
&& descriptor.getVisibility() == Visibilities.PUBLIC //TODO: what about protected and package-local?
|
&& descriptor.visibility == Visibilities.PUBLIC //TODO: what about protected and package-local?
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isGoodSetMethod(descriptor: FunctionDescriptor, propertyType: JetType): Boolean {
|
private fun isGoodSetMethod(descriptor: FunctionDescriptor, getMethod: FunctionDescriptor): Boolean {
|
||||||
val parameter = descriptor.getValueParameters().singleOrNull() ?: return false
|
val propertyType = getMethod.returnType ?: return false
|
||||||
return parameter.getType() == propertyType
|
val parameter = descriptor.valueParameters.singleOrNull() ?: return false
|
||||||
&& parameter.getVarargElementType() == null
|
if (parameter.type != propertyType) {
|
||||||
&& descriptor.getTypeParameters().isEmpty()
|
if (descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return false // real setter must exactly match getter's type
|
||||||
&& descriptor.getReturnType()?.let { it.isUnit() } ?: false
|
if (!propertyType.isSubtypeOf(parameter.type)) return false
|
||||||
&& descriptor.getVisibility() == Visibilities.PUBLIC
|
if (descriptor.findOverridden {
|
||||||
|
val baseProperty = SyntheticJavaPropertyDescriptor.findByGetterOrSetter(it, this)
|
||||||
|
baseProperty?.getMethod?.name == getMethod.name
|
||||||
|
} == null) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter.varargElementType == null
|
||||||
|
&& descriptor.typeParameters.isEmpty()
|
||||||
|
&& descriptor.returnType?.let { it.isUnit() } ?: false
|
||||||
|
&& descriptor.visibility == Visibilities.PUBLIC
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FunctionDescriptor.findOverridden(condition: (FunctionDescriptor) -> Boolean): FunctionDescriptor? {
|
||||||
|
for (descriptor in overriddenDescriptors) {
|
||||||
|
if (condition(descriptor)) return descriptor
|
||||||
|
descriptor.findOverridden(condition)?.let { return it }
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>, name: Name): Collection<PropertyDescriptor> {
|
override fun getSyntheticExtensionProperties(receiverTypes: Collection<JetType>, name: Name): Collection<PropertyDescriptor> {
|
||||||
@@ -161,7 +187,7 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
|
|
||||||
val typeConstructor = type.getConstructor()
|
val typeConstructor = type.getConstructor()
|
||||||
val classifier = typeConstructor.getDeclarationDescriptor()
|
val classifier = typeConstructor.getDeclarationDescriptor()
|
||||||
if (classifier is JavaClassDescriptor) {
|
if (classifier is ClassDescriptor) {
|
||||||
result = result.add(syntheticPropertyInClass(Pair(classifier, name)))
|
result = result.add(syntheticPropertyInClass(Pair(classifier, name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +210,7 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
|
|
||||||
val typeConstructor = type.getConstructor()
|
val typeConstructor = type.getConstructor()
|
||||||
val classifier = typeConstructor.getDeclarationDescriptor()
|
val classifier = typeConstructor.getDeclarationDescriptor()
|
||||||
if (classifier is JavaClassDescriptor) {
|
if (classifier is ClassDescriptor) {
|
||||||
for (descriptor in classifier.getUnsubstitutedMemberScope().getDescriptors(DescriptorKindFilter.FUNCTIONS)) {
|
for (descriptor in classifier.getUnsubstitutedMemberScope().getDescriptors(DescriptorKindFilter.FUNCTIONS)) {
|
||||||
if (descriptor is FunctionDescriptor) {
|
if (descriptor is FunctionDescriptor) {
|
||||||
val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(descriptor.getName()) ?: continue
|
val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(descriptor.getName()) ?: continue
|
||||||
@@ -233,13 +259,13 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class MyPropertyDescriptor(
|
private class MyPropertyDescriptor(
|
||||||
javaClass: JavaClassDescriptor,
|
ownerClass: ClassDescriptor,
|
||||||
override val getMethod: FunctionDescriptor,
|
override val getMethod: FunctionDescriptor,
|
||||||
override val setMethod: FunctionDescriptor?,
|
override val setMethod: FunctionDescriptor?,
|
||||||
name: Name,
|
name: Name,
|
||||||
type: JetType
|
type: JetType
|
||||||
) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl(
|
) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl(
|
||||||
DescriptorUtils.getContainingModule(javaClass)/* TODO:is it ok? */,
|
DescriptorUtils.getContainingModule(ownerClass)/* TODO:is it ok? */,
|
||||||
null,
|
null,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
@@ -250,12 +276,12 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
SourceElement.NO_SOURCE/*TODO?*/
|
SourceElement.NO_SOURCE/*TODO?*/
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
val classTypeParams = javaClass.typeConstructor.parameters
|
val classTypeParams = ownerClass.typeConstructor.parameters
|
||||||
val typeParameters = ArrayList<TypeParameterDescriptor>(classTypeParams.size())
|
val typeParameters = ArrayList<TypeParameterDescriptor>(classTypeParams.size())
|
||||||
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(classTypeParams, TypeSubstitutor.EMPTY, this, typeParameters)
|
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(classTypeParams, TypeSubstitutor.EMPTY, this, typeParameters)
|
||||||
|
|
||||||
val propertyType = typeSubstitutor.safeSubstitute(type, Variance.INVARIANT)
|
val propertyType = typeSubstitutor.safeSubstitute(type, Variance.INVARIANT)
|
||||||
val receiverType = typeSubstitutor.safeSubstitute(javaClass.defaultType, Variance.INVARIANT)
|
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
|
||||||
setType(propertyType, typeParameters, null, receiverType)
|
setType(propertyType, typeParameters, null, receiverType)
|
||||||
|
|
||||||
val getter = PropertyGetterDescriptorImpl(this,
|
val getter = PropertyGetterDescriptorImpl(this,
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
class JavaClass1 {
|
||||||
|
protected Object value = null;
|
||||||
|
|
||||||
|
public Object getSomething() { return null; }
|
||||||
|
public void setSomething(Object value) { this.value = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class JavaClass2 extends JavaClass1 {
|
||||||
|
public String getSomething() { return (String)value; }
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val javaClass = JavaClass2()
|
||||||
|
javaClass.something = "OK"
|
||||||
|
return javaClass.something
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
open class KotlinClass {
|
||||||
|
public open fun getSomething1(): Int = 1
|
||||||
|
|
||||||
|
public open fun setSomething2(value: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(javaClass: JavaClass) {
|
||||||
|
useInt(javaClass.getSomething1())
|
||||||
|
useInt(javaClass.<!UNRESOLVED_REFERENCE!>something1<!>)
|
||||||
|
|
||||||
|
javaClass.setSomething2(javaClass.getSomething2() + 1)
|
||||||
|
javaClass.something2 = javaClass.something2 + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useInt(<!UNUSED_PARAMETER!>i<!>: Int) {}
|
||||||
|
|
||||||
|
// FILE: JavaClass.java
|
||||||
|
public class JavaClass extends KotlinClass implements JavaInterface {
|
||||||
|
public int getSomething1() { return 1; }
|
||||||
|
|
||||||
|
public int getSomething2() { return 1; }
|
||||||
|
public void setSomething2(int value) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface.java
|
||||||
|
public class JavaInterface {
|
||||||
|
int getSomething2();
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
|
||||||
|
internal fun useInt(/*0*/ i: kotlin.Int): kotlin.Unit
|
||||||
|
|
||||||
|
public open class JavaClass : KotlinClass, JavaInterface {
|
||||||
|
public constructor JavaClass()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething1(): kotlin.Int
|
||||||
|
public open override /*1*/ fun getSomething2(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun setSomething2(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class JavaInterface {
|
||||||
|
public constructor JavaInterface()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public/*package*/ open fun getSomething2(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal open class KotlinClass {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun getSomething1(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun setSomething2(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
abstract class KotlinClass : JavaClass(), KotlinInterface, JavaInterface {
|
||||||
|
override fun getSomething1(): Int = 1
|
||||||
|
override fun getSomething3(): String = ""
|
||||||
|
override fun setSomething4(value: String) {}
|
||||||
|
override fun getSomething5(): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KotlinInterface {
|
||||||
|
public fun getSomething1(): Int
|
||||||
|
public fun getSomething4(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(k: KotlinClass) {
|
||||||
|
useInt(k.getSomething1())
|
||||||
|
useInt(k.something1)
|
||||||
|
|
||||||
|
useInt(k.getSomething2())
|
||||||
|
useInt(k.something2)
|
||||||
|
|
||||||
|
useString(k.getSomething3())
|
||||||
|
useString(k.something3)
|
||||||
|
|
||||||
|
k.setSomething4("")
|
||||||
|
k.something4 += ""
|
||||||
|
k.setSomething4(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
|
k.something4 = null
|
||||||
|
|
||||||
|
useString(k.getSomething5())
|
||||||
|
useString(k.something5)
|
||||||
|
k.setSomething5(1)
|
||||||
|
k.something5 = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useInt(<!UNUSED_PARAMETER!>i<!>: Int) {}
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaClass.java
|
||||||
|
public class JavaClass {
|
||||||
|
public int getSomething1() { return 1; }
|
||||||
|
public int getSomething2() { return 1; }
|
||||||
|
public Object getSomething3() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface.java
|
||||||
|
public interface JavaInterface {
|
||||||
|
String getSomething4();
|
||||||
|
void setSomething4(String value);
|
||||||
|
|
||||||
|
Object getSomething5();
|
||||||
|
void setSomething5(Object value);
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun foo(/*0*/ k: KotlinClass): kotlin.Unit
|
||||||
|
internal fun useInt(/*0*/ i: kotlin.Int): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public open class JavaClass {
|
||||||
|
public constructor JavaClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun getSomething1(): kotlin.Int
|
||||||
|
public open fun getSomething2(): kotlin.Int
|
||||||
|
public open fun getSomething3(): kotlin.Any!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething4(): kotlin.String!
|
||||||
|
public abstract fun getSomething5(): kotlin.Any!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun setSomething4(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public abstract fun setSomething5(/*0*/ value: kotlin.Any!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class KotlinClass : JavaClass, KotlinInterface, JavaInterface {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ fun getSomething1(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun getSomething2(): kotlin.Int
|
||||||
|
public open override /*1*/ fun getSomething3(): kotlin.String
|
||||||
|
public abstract override /*2*/ /*fake_override*/ fun getSomething4(): kotlin.String!
|
||||||
|
public open override /*1*/ fun getSomething5(): kotlin.String
|
||||||
|
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun setSomething4(/*0*/ value: kotlin.String): kotlin.Unit
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething5(/*0*/ value: kotlin.Any!): kotlin.Unit
|
||||||
|
public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface KotlinInterface {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething1(): kotlin.Int
|
||||||
|
public abstract fun getSomething4(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
abstract class KotlinClass : JavaInterface1, JavaInterface2 {
|
||||||
|
override fun getSomething(): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(k: KotlinClass) {
|
||||||
|
useString(k.getSomething())
|
||||||
|
useString(k.something)
|
||||||
|
if (<!SENSELESS_COMPARISON!>k.something == null<!>) return
|
||||||
|
|
||||||
|
k.setSomething(1)
|
||||||
|
<!VAL_REASSIGNMENT!>k.something<!> = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaInterface1.java
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
String getSomething();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface2.java
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
void setSomething(int value);
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public /*synthesized*/ fun JavaInterface1(/*0*/ function: () -> kotlin.String!): JavaInterface1
|
||||||
|
public /*synthesized*/ fun JavaInterface2(/*0*/ function: (kotlin.Int) -> kotlin.Unit): JavaInterface2
|
||||||
|
internal fun foo(/*0*/ k: KotlinClass): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
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 abstract fun setSomething(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class KotlinClass : JavaInterface1, JavaInterface2 {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething(): kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
abstract class KotlinClass : JavaInterface1, JavaInterface2 {
|
||||||
|
override fun getSomething(): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(k: KotlinClass) {
|
||||||
|
useString(k.getSomething())
|
||||||
|
useString(k.something)
|
||||||
|
if (<!SENSELESS_COMPARISON!>k.something == null<!>) return
|
||||||
|
|
||||||
|
k.setSomething("")
|
||||||
|
<!VAL_REASSIGNMENT!>k.something<!> = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaInterface1.java
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
String getSomething();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface2.java
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
void setSomething(String value);
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public /*synthesized*/ fun JavaInterface1(/*0*/ function: () -> kotlin.String!): JavaInterface1
|
||||||
|
public /*synthesized*/ fun JavaInterface2(/*0*/ function: (kotlin.String!) -> kotlin.Unit): JavaInterface2
|
||||||
|
internal fun foo(/*0*/ k: KotlinClass): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
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 abstract fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class KotlinClass : JavaInterface1, JavaInterface2 {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething(): kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
abstract class KotlinClass : JavaInterface3 {
|
||||||
|
override fun getSomething(): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(k: KotlinClass) {
|
||||||
|
useString(k.getSomething())
|
||||||
|
useString(k.something)
|
||||||
|
if (<!SENSELESS_COMPARISON!>k.something == null<!>) return
|
||||||
|
|
||||||
|
k.setSomething("")
|
||||||
|
<!VAL_REASSIGNMENT!>k.something<!> = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaInterface1.java
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
String getSomething();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface2.java
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
void setSomething(String value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface3.java
|
||||||
|
public interface JavaInterface3 extends JavaInterface1, JavaInterface2 {}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public /*synthesized*/ fun JavaInterface1(/*0*/ function: () -> kotlin.String!): JavaInterface1
|
||||||
|
public /*synthesized*/ fun JavaInterface2(/*0*/ function: (kotlin.String!) -> kotlin.Unit): JavaInterface2
|
||||||
|
internal fun foo(/*0*/ k: KotlinClass): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
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 abstract fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface3 : JavaInterface1, JavaInterface2 {
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun getSomething(): kotlin.String!
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class KotlinClass : JavaInterface3 {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
abstract class KotlinClass : JavaInterface3 {
|
||||||
|
override fun getSomething(): String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(k: KotlinClass) {
|
||||||
|
useString(k.getSomething())
|
||||||
|
useString(k.something)
|
||||||
|
if (<!SENSELESS_COMPARISON!>k.something == null<!>) return
|
||||||
|
|
||||||
|
k.setSomething("")
|
||||||
|
k.something = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaInterface1.java
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
String getSomething();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface2.java
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
String getSomething();
|
||||||
|
void setSomething(String value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaInterface3.java
|
||||||
|
public interface JavaInterface3 extends JavaInterface1, JavaInterface2 {}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public /*synthesized*/ fun JavaInterface1(/*0*/ function: () -> kotlin.String!): JavaInterface1
|
||||||
|
internal fun foo(/*0*/ k: KotlinClass): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public interface JavaInterface1 {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface2 {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface JavaInterface3 : JavaInterface1, JavaInterface2 {
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract override /*2*/ /*fake_override*/ fun getSomething(): kotlin.String!
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class KotlinClass : JavaInterface3 {
|
||||||
|
public constructor KotlinClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.String!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// FILE: KotlinFile.kt
|
||||||
|
|
||||||
|
fun foo(o: JavaClass2) {
|
||||||
|
useString(o.something)
|
||||||
|
o.something = ""
|
||||||
|
o.setSomething(1)
|
||||||
|
o.something = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> // we generate extension property for JavaClass2 with more specific type
|
||||||
|
o.something += "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useString(<!UNUSED_PARAMETER!>i<!>: String) {}
|
||||||
|
|
||||||
|
// FILE: JavaClass1.java
|
||||||
|
public class JavaClass1 {
|
||||||
|
public Object getSomething() { return null; }
|
||||||
|
public void setSomething(Object value) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaClass2.java
|
||||||
|
public class JavaClass2 extends JavaClass1 {
|
||||||
|
public String getSomething() { return ""; }
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun foo(/*0*/ o: JavaClass2): kotlin.Unit
|
||||||
|
internal fun useString(/*0*/ i: kotlin.String): kotlin.Unit
|
||||||
|
|
||||||
|
public open class JavaClass1 {
|
||||||
|
public constructor JavaClass1()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun getSomething(): kotlin.Any!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun setSomething(/*0*/ value: kotlin.Any!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class JavaClass2 : JavaClass1 {
|
||||||
|
public constructor JavaClass2()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ fun getSomething(): kotlin.String!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun setSomething(/*0*/ value: kotlin.Any!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -14082,12 +14082,54 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JavaOverridesKotlin.kt")
|
||||||
|
public void testJavaOverridesKotlin() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/JavaOverridesKotlin.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KotlinOverridesJava.kt")
|
||||||
|
public void testKotlinOverridesJava() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/KotlinOverridesJava.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KotlinOverridesJava2.kt")
|
||||||
|
public void testKotlinOverridesJava2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/KotlinOverridesJava2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KotlinOverridesJava3.kt")
|
||||||
|
public void testKotlinOverridesJava3() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/KotlinOverridesJava3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KotlinOverridesJava4.kt")
|
||||||
|
public void testKotlinOverridesJava4() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/KotlinOverridesJava4.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KotlinOverridesJava5.kt")
|
||||||
|
public void testKotlinOverridesJava5() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/KotlinOverridesJava5.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OnlyPublic.kt")
|
@TestMetadata("OnlyPublic.kt")
|
||||||
public void testOnlyPublic() throws Exception {
|
public void testOnlyPublic() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/OnlyPublic.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/OnlyPublic.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverrideGetterOnly.kt")
|
||||||
|
public void testOverrideGetterOnly() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/OverrideGetterOnly.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("SetterOnly.kt")
|
@TestMetadata("SetterOnly.kt")
|
||||||
public void testSetterOnly() throws Exception {
|
public void testSetterOnly() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/SetterOnly.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/SetterOnly.kt");
|
||||||
|
|||||||
+6
@@ -847,6 +847,12 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
|
|||||||
doTestAgainstJava(fileName);
|
doTestAgainstJava(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideOnlyGetter.kt")
|
||||||
|
public void testOverrideOnlyGetter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/overrideOnlyGetter.kt");
|
||||||
|
doTestAgainstJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("plusPlus.kt")
|
@TestMetadata("plusPlus.kt")
|
||||||
public void testPlusPlus() throws Exception {
|
public void testPlusPlus() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/plusPlus.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/plusPlus.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user