Kotlin: Give fields a Kotlin type

This meant refactoring the EnumEntry extraction a bit. The IR doesn't
give us a type for fields, so we have to make it up based on the parent.
This commit is contained in:
Ian Lynagh
2021-11-03 11:21:18 +00:00
parent e120059a18
commit c20ee76826
6 changed files with 50 additions and 34 deletions

View File

@@ -389,6 +389,31 @@ open class KotlinUsesExtractor(
return id return id
} }
fun useSimpleTypeClass(c: IrClass, args: List<IrTypeArgument>, hasQuestionMark: Boolean): TypeResults {
val classInstanceResult = useClassInstance(c, args)
val javaClassId = classInstanceResult.classLabel
val kotlinQualClassName = getUnquotedClassLabel(c, args)
val javaQualClassName = classInstanceResult.javaClass.fqNameForIrSerialization.asString()
val javaSignature = javaQualClassName // TODO: Is this right?
val javaResult = TypeResult(javaClassId, javaSignature)
val kotlinResult = if (hasQuestionMark) {
val kotlinSignature = "$kotlinQualClassName?" // TODO: Is this right?
val kotlinLabel = "@\"kt_type;nullable;$kotlinQualClassName\""
val kotlinId: Label<DbKt_nullable_type> = tw.getLabelFor(kotlinLabel, {
tw.writeKt_nullable_types(it, javaClassId)
})
TypeResult(kotlinId, kotlinSignature)
} else {
val kotlinSignature = kotlinQualClassName // TODO: Is this right?
val kotlinLabel = "@\"kt_type;notnull;$kotlinQualClassName\""
val kotlinId: Label<DbKt_notnull_type> = tw.getLabelFor(kotlinLabel, {
tw.writeKt_notnull_types(it, javaClassId)
})
TypeResult(kotlinId, kotlinSignature)
}
return TypeResults(javaResult, kotlinResult)
}
fun useSimpleType(s: IrSimpleType, canReturnPrimitiveTypes: Boolean): TypeResults { fun useSimpleType(s: IrSimpleType, canReturnPrimitiveTypes: Boolean): TypeResults {
// We use this when we don't actually have an IrClass for a class // We use this when we don't actually have an IrClass for a class
// we want to refer to // we want to refer to
@@ -514,28 +539,7 @@ class X {
val classifier: IrClassifierSymbol = s.classifier val classifier: IrClassifierSymbol = s.classifier
val cls: IrClass = classifier.owner as IrClass val cls: IrClass = classifier.owner as IrClass
val classInstanceResult = useClassInstance(cls, s.arguments) return useSimpleTypeClass(cls, s.arguments, s.hasQuestionMark)
val javaClassId = classInstanceResult.classLabel
val kotlinQualClassName = getUnquotedClassLabel(cls, s.arguments)
val javaQualClassName = classInstanceResult.javaClass.fqNameForIrSerialization.asString()
val javaSignature = javaQualClassName // TODO: Is this right?
val javaResult = TypeResult(javaClassId, javaSignature)
val kotlinResult = if (s.hasQuestionMark) {
val kotlinSignature = "$kotlinQualClassName?" // TODO: Is this right?
val kotlinLabel = "@\"kt_type;nullable;$kotlinQualClassName\""
val kotlinId: Label<DbKt_nullable_type> = tw.getLabelFor(kotlinLabel, {
tw.writeKt_nullable_types(it, javaClassId)
})
TypeResult(kotlinId, kotlinSignature)
} else {
val kotlinSignature = kotlinQualClassName // TODO: Is this right?
val kotlinLabel = "@\"kt_type;notnull;$kotlinQualClassName\""
val kotlinId: Label<DbKt_notnull_type> = tw.getLabelFor(kotlinLabel, {
tw.writeKt_notnull_types(it, javaClassId)
})
TypeResult(kotlinId, kotlinSignature)
}
return TypeResults(javaResult, kotlinResult)
} }
s.classifier.owner is IrTypeParameter -> { s.classifier.owner is IrTypeParameter -> {
val javaId = useTypeParameter(s.classifier.owner as IrTypeParameter) val javaId = useTypeParameter(s.classifier.owner as IrTypeParameter)
@@ -1006,8 +1010,8 @@ open class KotlinFileExtractor(
} else { } else {
val id = useProperty(p) val id = useProperty(p)
val locId = tw.getLocation(p) val locId = tw.getLocation(p)
val typeId = useTypeOld(bf.type) val type = useType(bf.type)
tw.writeFields(id, p.name.asString(), typeId, parentId, id) tw.writeFields(id, p.name.asString(), type.javaResult.id, type.kotlinResult.id, parentId, id)
tw.writeHasLocation(id, locId) tw.writeHasLocation(id, locId)
} }
} }
@@ -1015,8 +1019,16 @@ open class KotlinFileExtractor(
fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>) { fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>) {
val id = useEnumEntry(ee) val id = useEnumEntry(ee)
val locId = tw.getLocation(ee) val locId = tw.getLocation(ee)
tw.writeFields(id, ee.name.asString(), parentId, parentId, id) val parent = ee.parent
tw.writeHasLocation(id, locId) if(parent !is IrClass) {
logger.warnElement(Severity.ErrorSevere, "Enum entry with unexpected parent: " + parent.javaClass, ee)
} else if (!parent.typeParameters.isEmpty()) {
logger.warnElement(Severity.ErrorSevere, "Enum entry parent class has type parameters: " + parent.name, ee)
} else {
val type = useSimpleTypeClass(parent, emptyList(), false)
tw.writeFields(id, ee.name.asString(), type.javaResult.id, type.kotlinResult.id, parentId, id)
tw.writeHasLocation(id, locId)
}
} }
fun extractBody(b: IrBody, callable: Label<out DbCallable>) { fun extractBody(b: IrBody, callable: Label<out DbCallable>) {

View File

@@ -353,6 +353,7 @@ fields(
unique int id: @field, unique int id: @field,
string nodeName: string ref, string nodeName: string ref,
int typeid: @type ref, int typeid: @type ref,
int kttypeid: @kt_type ref,
int parentid: @reftype ref, int parentid: @reftype ref,
int sourceid: @field ref int sourceid: @field ref
); );

View File

@@ -20,7 +20,7 @@ predicate hasName(Element e, string name) {
or or
methods(e, name, _, _, _, _) methods(e, name, _, _, _, _)
or or
fields(e, name, _, _, _) fields(e, name, _, _, _, _)
or or
packages(e, name) packages(e, name)
or or

View File

@@ -63,7 +63,7 @@ private predicate hasChildElement(Element parent, Element e) {
or or
params(e, _, _, parent, _) params(e, _, _, parent, _)
or or
fields(e, _, _, parent, _) fields(e, _, _, _, parent, _)
or or
typeVars(e, _, _, _, parent) typeVars(e, _, _, _, parent)
} }

View File

@@ -598,10 +598,13 @@ class FieldDeclaration extends ExprParent, @fielddecl, Annotatable {
/** A class or instance field. */ /** A class or instance field. */
class Field extends Member, ExprParent, @field, Variable { class Field extends Member, ExprParent, @field, Variable {
/** Gets the declared type of this field. */ /** Gets the declared type of this field. */
override Type getType() { fields(this, _, result, _, _) } override Type getType() { fields(this, _, result, _, _, _) }
/** Gets the Kotlin type of this field. */
KotlinType getKotlinType() { fields(this, _, _, result, _, _) }
/** Gets the type in which this field is declared. */ /** Gets the type in which this field is declared. */
override RefType getDeclaringType() { fields(this, _, _, result, _) } override RefType getDeclaringType() { fields(this, _, _, _, result, _) }
/** /**
* Gets the field declaration in which this field is declared. * Gets the field declaration in which this field is declared.
@@ -631,7 +634,7 @@ class Field extends Member, ExprParent, @field, Variable {
* *
* For all other fields, the source declaration is the field itself. * For all other fields, the source declaration is the field itself.
*/ */
Field getSourceDeclaration() { fields(this, _, _, _, result) } Field getSourceDeclaration() { fields(this, _, _, _, _, result) }
/** Holds if this field is the same as its source declaration. */ /** Holds if this field is the same as its source declaration. */
predicate isSourceDeclaration() { this.getSourceDeclaration() = this } predicate isSourceDeclaration() { this.getSourceDeclaration() = this }

View File

@@ -319,7 +319,7 @@ predicate declaresMember(Type t, @member m) {
or or
constrs(m, _, _, _, t, _) constrs(m, _, _, _, t, _)
or or
fields(m, _, _, t, _) fields(m, _, _, _, t, _)
or or
enclInReftype(m, t) and enclInReftype(m, t) and
// Since the type `@member` in the dbscheme includes all `@reftype`s, // Since the type `@member` in the dbscheme includes all `@reftype`s,
@@ -1109,11 +1109,11 @@ class EnumType extends Class {
/** Gets the enum constant with the specified name. */ /** Gets the enum constant with the specified name. */
EnumConstant getEnumConstant(string name) { EnumConstant getEnumConstant(string name) {
fields(result, _, _, this, _) and result.hasName(name) fields(result, _, _, _, this, _) and result.hasName(name)
} }
/** Gets an enum constant declared in this enum type. */ /** Gets an enum constant declared in this enum type. */
EnumConstant getAnEnumConstant() { fields(result, _, _, this, _) } EnumConstant getAnEnumConstant() { fields(result, _, _, _, this, _) }
override predicate isFinal() { override predicate isFinal() {
// JLS 8.9: An enum declaration is implicitly `final` unless it contains // JLS 8.9: An enum declaration is implicitly `final` unless it contains