[FIR] Support Clonable

#KT-36762 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-03-05 18:12:48 +03:00
parent 83d01fbaaa
commit af67aff303
10 changed files with 185 additions and 43 deletions
@@ -5,22 +5,24 @@
package org.jetbrains.kotlin.fir.deserialization
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.addDeclarations
import org.jetbrains.kotlin.fir.declarations.builder.FirClassImplBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirSealedClassBuilder
import org.jetbrains.kotlin.fir.declarations.builder.buildEnumEntry
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.impl.FirClonableSymbolProvider.Companion.CLONE
import org.jetbrains.kotlin.fir.resolve.impl.FirClonableSymbolProvider.Companion.CLONABLE_CLASS_ID
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
@@ -133,7 +135,58 @@ fun deserializeClassToSymbol(
ClassId.fromString(nameResolver.getQualifiedClassName(it))
}
}
addCloneForArrayIfNeeded(classId)
}.build().also {
(it.annotations as MutableList<FirAnnotationCall>) += context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
}
}
private val ARRAY = Name.identifier("Array")
private val ARRAY_CLASSES: Set<Name> = setOf(
ARRAY,
Name.identifier("ByteArray"),
Name.identifier("CharArray"),
Name.identifier("ShortArray"),
Name.identifier("IntArray"),
Name.identifier("LongArray"),
Name.identifier("FloatArray"),
Name.identifier("DoubleArray"),
Name.identifier("BooleanArray"),
)
private fun AbstractFirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId) {
if (classId.packageFqName != KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) return
if (classId.shortClassName !in ARRAY_CLASSES) return
superTypeRefs += buildResolvedTypeRef {
type = ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(CLONABLE_CLASS_ID),
typeArguments = emptyArray(),
isNullable = false
)
}
declarations += buildSimpleFunction {
session = this@addCloneForArrayIfNeeded.session
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
returnTypeRef = buildResolvedTypeRef {
val typeArguments = if (classId.shortClassName == ARRAY) {
arrayOf(
ConeTypeParameterTypeImpl(
ConeTypeParameterLookupTag(this@addCloneForArrayIfNeeded.typeParameters.first().symbol), isNullable = false
)
)
} else {
emptyArray()
}
type = ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(classId),
typeArguments = typeArguments,
isNullable = false
)
}
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL).apply {
isOverride = true
}
name = CLONE
symbol = FirNamedFunctionSymbol(CallableId(classId, CLONE))
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildClassImpl
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class FirClonableSymbolProvider(session: FirSession, scopeProvider: FirScopeProvider) : FirSymbolProvider() {
companion object {
val CLONABLE: Name = Name.identifier("Cloneable")
val CLONABLE_CLASS_ID: ClassId = ClassId(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME, CLONABLE)
val CLONE: Name = Name.identifier("clone")
}
private val klass = buildClassImpl {
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
this.session = session
status = FirDeclarationStatusImpl(
Visibilities.PUBLIC,
Modality.ABSTRACT
)
classKind = ClassKind.INTERFACE
declarations += buildSimpleFunction {
this.session = session
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
returnTypeRef = buildResolvedTypeRef {
type = session.builtinTypes.anyType.type
}
status = FirDeclarationStatusImpl(Visibilities.PROTECTED, Modality.OPEN)
name = CLONE
symbol = FirNamedFunctionSymbol(CallableId(CLONABLE_CLASS_ID, CLONE))
}
this.scopeProvider = scopeProvider
name = CLONABLE
symbol = FirRegularClassSymbol(CLONABLE_CLASS_ID)
}
override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? {
return if (classId == CLONABLE_CLASS_ID) klass.symbol else null
}
override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
return emptyList()
}
override fun getNestedClassifierScope(classId: ClassId): FirScope? {
return null
}
override fun getPackage(fqName: FqName): FqName? {
return null
}
}
+27 -9
View File
@@ -42,7 +42,7 @@ public open class Any {
}
public final class Array<T> : R|kotlin/Any| {
public final class Array<T> : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|T|
public final operator fun iterator(): R|kotlin/collections/Iterator<T>|
@@ -54,6 +54,8 @@ public final class Array<T> : R|kotlin/Any| {
public constructor<T>(size: R|kotlin/Int|, init: R|(kotlin/Int) -> T|): R|kotlin/Array<T>|
public final override fun clone(): R|kotlin/Array<T>|
}
public final class Boolean : R|kotlin/Comparable<kotlin/Boolean>| {
@@ -76,7 +78,7 @@ public final class Boolean : R|kotlin/Comparable<kotlin/Boolean>| {
}
public final class BooleanArray : R|kotlin/Any| {
public final class BooleanArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Boolean|
public final operator fun iterator(): R|kotlin/collections/BooleanIterator|
@@ -90,6 +92,8 @@ public final class BooleanArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/BooleanArray|
public final override fun clone(): R|kotlin/BooleanArray|
}
public final class Byte : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Byte>| {
@@ -216,7 +220,7 @@ public final class Byte : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Byte>| {
}
public final class ByteArray : R|kotlin/Any| {
public final class ByteArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Byte|
public final operator fun iterator(): R|kotlin/collections/ByteIterator|
@@ -230,6 +234,8 @@ public final class ByteArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/ByteArray|
public final override fun clone(): R|kotlin/ByteArray|
}
public final class Char : R|kotlin/Comparable<kotlin/Char>| {
@@ -300,7 +306,7 @@ public final class Char : R|kotlin/Comparable<kotlin/Char>| {
}
public final class CharArray : R|kotlin/Any| {
public final class CharArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Char|
public final operator fun iterator(): R|kotlin/collections/CharIterator|
@@ -314,6 +320,8 @@ public final class CharArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/CharArray|
public final override fun clone(): R|kotlin/CharArray|
}
public abstract interface CharSequence : R|kotlin/Any| {
@@ -477,7 +485,7 @@ public final class Double : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Double>
}
public final class DoubleArray : R|kotlin/Any| {
public final class DoubleArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Double|
public final operator fun iterator(): R|kotlin/collections/DoubleIterator|
@@ -491,6 +499,8 @@ public final class DoubleArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/DoubleArray|
public final override fun clone(): R|kotlin/DoubleArray|
}
@R|kotlin/annotation/Target|() @R|kotlin/annotation/Retention|(value = R|kotlin/annotation/AnnotationRetention.BINARY|()) @R|kotlin/annotation/MustBeDocumented|() @R|kotlin/SinceKotlin|(version = String(1.1)) public final annotation class DslMarker : R|kotlin/Annotation| {
@@ -648,7 +658,7 @@ public final class Float : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Float>|
}
public final class FloatArray : R|kotlin/Any| {
public final class FloatArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Float|
public final operator fun iterator(): R|kotlin/collections/FloatIterator|
@@ -662,6 +672,8 @@ public final class FloatArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/FloatArray|
public final override fun clone(): R|kotlin/FloatArray|
}
public abstract interface Function<out R> : R|kotlin/Any| {
@@ -805,7 +817,7 @@ public final class Int : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Int>| {
}
public final class IntArray : R|kotlin/Any| {
public final class IntArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Int|
public final operator fun iterator(): R|kotlin/collections/IntIterator|
@@ -819,6 +831,8 @@ public final class IntArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/IntArray|
public final override fun clone(): R|kotlin/IntArray|
}
public final class Long : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Long>| {
@@ -959,7 +973,7 @@ public final class Long : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Long>| {
}
public final class LongArray : R|kotlin/Any| {
public final class LongArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Long|
public final operator fun iterator(): R|kotlin/collections/LongIterator|
@@ -973,6 +987,8 @@ public final class LongArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/LongArray|
public final override fun clone(): R|kotlin/LongArray|
}
public final class Nothing {
@@ -1147,7 +1163,7 @@ public final class Short : R|kotlin/Number|, R|kotlin/Comparable<kotlin/Short>|
}
public final class ShortArray : R|kotlin/Any| {
public final class ShortArray : R|kotlin/Any|, R|kotlin/Cloneable| {
public final operator fun get(index: R|kotlin/Int|): R|kotlin/Short|
public final operator fun iterator(): R|kotlin/collections/ShortIterator|
@@ -1161,6 +1177,8 @@ public final class ShortArray : R|kotlin/Any| {
public constructor(size: R|kotlin/Int|): R|kotlin/ShortArray|
public final override fun clone(): R|kotlin/ShortArray|
}
@R|kotlin/annotation/Target|() @R|kotlin/annotation/Retention|(value = R|kotlin/annotation/AnnotationRetention.BINARY|()) @R|kotlin/annotation/MustBeDocumented|() public final annotation class SinceKotlin : R|kotlin/Annotation| {
@@ -1,7 +1,7 @@
fun test_1(array: Array<String>) {
array.<!UNRESOLVED_REFERENCE!>clone<!>()
array.clone()
}
fun test_2(array: IntArray) {
array.<!UNRESOLVED_REFERENCE!>clone<!>()
array.clone()
}
@@ -1,7 +1,7 @@
FILE: cloneArray.kt
public final fun test_1(array: R|kotlin/Array<kotlin/String>|): R|kotlin/Unit| {
R|<local>/array|.<Unresolved name: clone>#()
R|<local>/array|.R|FakeOverride<kotlin/Array.clone: R|kotlin/Array<kotlin/String>|>|()
}
public final fun test_2(array: R|kotlin/IntArray|): R|kotlin/Unit| {
R|<local>/array|.<Unresolved name: clone>#()
R|<local>/array|.R|kotlin/IntArray.clone|()
}