diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 42617078ff54..7f2b0501a62b 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2776,7 +2776,7 @@ open class KotlinFileExtractor( val locId = tw.getLocation(ta) // TODO: We don't really want to generate any Java types here; we only want the KT type: val type = useType(ta.expandedType) - tw.writeKt_type_alias(id, ta.name.asString(), type.kotlinResult.id) + TODO() // TODO: KotType tw.writeKt_type_alias(id, ta.name.asString(), type.kotlinResult.id) tw.writeHasLocation(id, locId) // TODO: extract annotations @@ -7569,11 +7569,11 @@ open class KotlinFileExtractor( val locId = tw.getLocation(propertyReferenceExpr) val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") - val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") - tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) + TODO() // TODO:KotType val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") + TODO() // TODO:KotType tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = GeneratedClassLabels( - TypeResults(javaResult, kotlinResult), + TODO(), // TODO:KotType TypeResults(javaResult, kotlinResult), constructor = tw.getFreshIdLabel(), constructorBlock = tw.getFreshIdLabel() ) @@ -7669,6 +7669,8 @@ open class KotlinFileExtractor( classId, locId ) + TODO() // TODO:KotType + /* val fieldId = useField(backingField.owner) helper.extractFieldReturnOfReflectionTarget(getLabels, backingField) @@ -7680,6 +7682,7 @@ open class KotlinFileExtractor( getterParameterTypes, getterReturnType ) + */ } if (setter != null) { @@ -7890,11 +7893,11 @@ open class KotlinFileExtractor( val locId = tw.getLocation(functionReferenceExpr) val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") - val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") - tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) + TODO() // TODO:KotType val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") + TODO() // TODO:KotType tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = LocallyVisibleFunctionLabels( - TypeResults(javaResult, kotlinResult), + TODO(), // TODO:KotType TypeResults(javaResult, kotlinResult), constructor = tw.getFreshIdLabel(), function = tw.getFreshIdLabel(), constructorBlock = tw.getFreshIdLabel() @@ -8782,11 +8785,11 @@ open class KotlinFileExtractor( } val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") - val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") - tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) + TODO() // TODO:KotType val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") + TODO() // TODO:KotType tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) val ids = LocallyVisibleFunctionLabels( - TypeResults(javaResult, kotlinResult), + TODO(), // TODO:KotType TypeResults(javaResult, kotlinResult), constructor = tw.getFreshIdLabel(), constructorBlock = tw.getFreshIdLabel(), function = tw.getFreshIdLabel() diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 03b74db19fac..bad6d0292ef2 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -126,13 +126,13 @@ open class KotlinUsesExtractor( private fun extractErrorType(): TypeResults { val javaResult = extractJavaErrorType() - val kotlinTypeId = - tw.getLabelFor("@\"errorKotlinType\"") { - tw.writeKt_nullable_types(it, javaResult.id) - } + TODO() // TODO:KotType val kotlinTypeId = + TODO() // TODO:KotType tw.getLabelFor("@\"errorKotlinType\"") { + TODO() // TODO:KotType tw.writeKt_nullable_types(it, javaResult.id) + TODO() // TODO:KotType } return TypeResults( javaResult, - TypeResult(kotlinTypeId, "", "") + TODO() // TODO:KotType TypeResult(kotlinTypeId, "", "") ) } @@ -635,12 +635,12 @@ open class KotlinUsesExtractor( "@\"FakeKotlinClass\"", { tw.writeClasses_or_interfaces(it, "FakeKotlinClass", fakeKotlinPackageId, it) } ) - val fakeKotlinTypeId: Label = - tw.getLabelFor( - "@\"FakeKotlinType\"", - { tw.writeKt_nullable_types(it, fakeKotlinClassId) } - ) - return fakeKotlinTypeId + TODO() // TODO:KotType val fakeKotlinTypeId: Label = + TODO() // TODO:KotType tw.getLabelFor( + TODO() // TODO:KotType "@\"FakeKotlinType\"", + TODO() // TODO:KotType { tw.writeKt_nullable_types(it, fakeKotlinClassId) } + TODO() // TODO:KotType ) + TODO() // TODO:KotType return fakeKotlinTypeId } // `args` can be null to describe a raw generic type. @@ -659,15 +659,15 @@ open class KotlinUsesExtractor( else if (hasQuestionMark) { val kotlinSignature = "$kotlinQualClassName?" // TODO: Is this right? val kotlinLabel = "@\"kt_type;nullable;$kotlinQualClassName\"" - val kotlinId: Label = - tw.getLabelFor(kotlinLabel, { tw.writeKt_nullable_types(it, javaClassId) }) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor(kotlinLabel, { tw.writeKt_nullable_types(it, javaClassId) }) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } else { val kotlinSignature = kotlinQualClassName // TODO: Is this right? val kotlinLabel = "@\"kt_type;notnull;$kotlinQualClassName\"" - val kotlinId: Label = - tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, javaClassId) }) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, javaClassId) }) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } return TypeResults(javaResult, kotlinResult) } @@ -864,19 +864,19 @@ open class KotlinUsesExtractor( val kotlinSignature = "$kotlinPackageName.$kotlinClassName?" // TODO: Is this right? val kotlinLabel = "@\"kt_type;nullable;$kotlinPackageName.$kotlinClassName\"" - val kotlinId: Label = - tw.getLabelFor( - kotlinLabel, - { tw.writeKt_nullable_types(it, kotlinClassId) } - ) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor( + TODO() // TODO:KotType kotlinLabel, + TODO() // TODO:KotType { tw.writeKt_nullable_types(it, kotlinClassId) } + TODO() // TODO:KotType ) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } else { val kotlinSignature = "$kotlinPackageName.$kotlinClassName" // TODO: Is this right? val kotlinLabel = "@\"kt_type;notnull;$kotlinPackageName.$kotlinClassName\"" - val kotlinId: Label = - tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, kotlinClassId) }) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, kotlinClassId) }) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } return TypeResults(javaResult, kotlinResult) } @@ -919,15 +919,15 @@ open class KotlinUsesExtractor( else if (s.isNullable()) { val kotlinSignature = "${javaResult.signature}?" // TODO: Wrong val kotlinLabel = "@\"kt_type;nullable;type_param\"" // TODO: Wrong - val kotlinId: Label = - tw.getLabelFor(kotlinLabel, { tw.writeKt_nullable_types(it, aClassId) }) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor(kotlinLabel, { tw.writeKt_nullable_types(it, aClassId) }) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } else { val kotlinSignature = javaResult.signature // TODO: Wrong val kotlinLabel = "@\"kt_type;notnull;type_param\"" // TODO: Wrong - val kotlinId: Label = - tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, aClassId) }) - TypeResult(kotlinId, kotlinSignature, "TODO") + TODO() // TODO:KotType val kotlinId: Label = + TODO() // TODO:KotType tw.getLabelFor(kotlinLabel, { tw.writeKt_notnull_types(it, aClassId) }) + TODO() // TODO:KotType TypeResult(kotlinId, kotlinSignature, "TODO") } return TypeResults(javaResult, kotlinResult) } @@ -1621,8 +1621,8 @@ open class KotlinUsesExtractor( var res = tw.lm.locallyVisibleFunctionLabelMapping[f] if (res == null) { val javaResult = TypeResult(tw.getFreshIdLabel(), "", "") - val kotlinResult = TypeResult(tw.getFreshIdLabel(), "", "") - tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) + val kotlinResult = TODO() // TODO:KotType TypeResult(tw.getFreshIdLabel(), "", "") + TODO() // TODO:KotType tw.writeKt_notnull_types(kotlinResult.id, javaResult.id) res = LocallyVisibleFunctionLabels( TypeResults(javaResult, kotlinResult), diff --git a/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt b/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt index ae98127eef97..18b7a00ead43 100644 --- a/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt +++ b/java/kotlin-extractor2/src/main/kotlin/entities/Types.kt @@ -9,31 +9,48 @@ private fun KotlinUsesExtractor.useClassType( c: KaClassType ): TypeResults { // TODO: this cast is unsafe; .symbol is actually a KaClassLikeSymbol - val javaResult = TypeResult(addClassLabel(c.symbol as KaClassSymbol) /* , TODO, TODO */) - val kotlinResult = TypeResult(fakeKotlinType() /* , "TODO", "TODO" */) + val classId = addClassLabel(c.symbol as KaClassSymbol) + val javaResult = TypeResult(classId /* , TODO, TODO */) + val kotlinTypeId = + tw.getLabelFor("@\"kt_class;{$classId}\"") { + tw.writeKt_class_types(it, classId) + } + val kotlinResult = TypeResult(kotlinTypeId /* , "TODO", "TODO" */) return TypeResults(javaResult, kotlinResult) } fun KotlinUsesExtractor.useType(t: KaType?, context: TypeContext = TypeContext.OTHER): TypeResults { - when (t) { + val tr = when (t) { null -> { logger.error("Unexpected null type") return extractErrorType() } - is KaClassType -> return useClassType(t) - is KaFlexibleType -> return useType(t.lowerBound) // TODO: take a more reasoned choice here + is KaClassType -> useClassType(t) + is KaFlexibleType -> useType(t.lowerBound) // TODO: take a more reasoned choice here else -> TODO() } - /* - OLD: KE1 - when (t) { - is IrSimpleType -> return useSimpleType(t, context) - else -> { - logger.error("Unrecognised IrType: " + t.javaClass) - return extractErrorType() - } - } - */ + val javaResult = tr.javaResult + val kotlinResultBase = tr.kotlinResult + val abbreviation = t.abbreviatedType + val kotlinResultAlias = if (abbreviation == null) kotlinResultBase else { + // TODO: this cast is unsafe; .symbol is actually a KaClassLikeSymbol + val classId = addClassLabel(abbreviation.symbol as KaClassSymbol) + val kotlinBaseTypeId = kotlinResultBase.id + val kotlinAliasTypeId = + tw.getLabelFor("@\"kt_type_alias;{$classId};{$kotlinBaseTypeId}\"") { + tw.writeKt_type_aliases(it, classId, kotlinBaseTypeId) + } + TypeResult(kotlinAliasTypeId /* , "TODO", "TODO" */) + } + val kotlinResultNullability = if (t.nullability.isNullable) { + val kotlinAliasTypeId = kotlinResultAlias.id + val kotlinNullableTypeId = + tw.getLabelFor("@\"kt_nullable_type;{$kotlinAliasTypeId}\"") { + tw.writeKt_nullable_types(it, kotlinAliasTypeId) + } + TypeResult(kotlinNullableTypeId /* , "TODO", "TODO" */) + } else kotlinResultAlias + return TypeResults(javaResult, kotlinResultNullability) } private fun KotlinUsesExtractor.extractJavaErrorType(): TypeResult { @@ -44,8 +61,8 @@ private fun KotlinUsesExtractor.extractJavaErrorType(): TypeResult private fun KotlinUsesExtractor.extractErrorType(): TypeResults { val javaResult = extractJavaErrorType() val kotlinTypeId = - tw.getLabelFor("@\"errorKotlinType\"") { - tw.writeKt_nullable_types(it, javaResult.id) + tw.getLabelFor("@\"errorKotlinType\"") { + tw.writeKt_error_types(it) } return TypeResults( javaResult, @@ -53,23 +70,6 @@ private fun KotlinUsesExtractor.extractErrorType(): TypeResults { ) } -// TODO -fun KotlinUsesExtractor.fakeKotlinType(): Label { - val fakeKotlinPackageId: Label = - tw.getLabelFor("@\"FakeKotlinPackage\"", { tw.writePackages(it, "fake.kotlin") }) - val fakeKotlinClassId: Label = - tw.getLabelFor( - "@\"FakeKotlinClass\"", - { tw.writeClasses_or_interfaces(it, "FakeKotlinClass", fakeKotlinPackageId, it) } - ) - val fakeKotlinTypeId: Label = - tw.getLabelFor( - "@\"FakeKotlinType\"", - { tw.writeKt_nullable_types(it, fakeKotlinClassId) } - ) - return fakeKotlinTypeId -} - /* OLD: KE1 // `args` can be null to describe a raw generic type. diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index e0fd7f76ab86..c34f54a5b28f 100644 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -461,23 +461,41 @@ type_companion_object( unique int companion_object: @classorinterface ref ); -kt_nullable_types( - unique int id: @kt_nullable_type, +/** + * `id` is the Kotlin type for the non-nullable class type `classid`. + */ +kt_class_types( + unique int id: @kt_class_type, int classid: @reftype ref ) -kt_notnull_types( - unique int id: @kt_notnull_type, - int classid: @reftype ref +/** + * `id` is the Kotlin type that is the same as `kttypeid`, but is nullable. + */ +kt_nullable_types( + unique int id: @kt_nullable_type, + int kttypeid: @kt_type ref ) -kt_type_alias( +/** + * `id` is the Kotlin type that is the alias called `classid` of `kttypeid`. + * That is, it has been defined by `typealias classid = kttypeid`. + */ +kt_type_aliases( unique int id: @kt_type_alias, - string name: string ref, + int classid: @reftype ref, int kttypeid: @kt_type ref ) -@kt_type = @kt_nullable_type | @kt_notnull_type +/** + * A `kt_error_type` is used when the extractor is unable to extract a type + * correctly for some reason. + */ +kt_error_types( + unique int id: @kt_error_type +) + +@kt_type = @kt_class_type | @kt_nullable_type | @kt_type_alias | @kt_error_type /** * This holds if `id` is an `interface`, rather than a `class`. diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll index abc1d19d0f89..a50efda799d7 100644 --- a/java/ql/lib/semmle/code/Location.qll +++ b/java/ql/lib/semmle/code/Location.qll @@ -42,8 +42,10 @@ predicate hasName(Element e, string name) { or modifiers(e, name) or - kt_type_alias(e, name, _) - or + // TODO: An alias declaration might have a name, but the type that + // uses it doesn't + // or + // kt_type_alias(e, name, _) ktProperties(e, name) or e instanceof ErrorType and name = "" diff --git a/java/ql/lib/semmle/code/java/KotlinType.qll b/java/ql/lib/semmle/code/java/KotlinType.qll index 3e5597c5579d..7735b984acd2 100644 --- a/java/ql/lib/semmle/code/java/KotlinType.qll +++ b/java/ql/lib/semmle/code/java/KotlinType.qll @@ -8,28 +8,33 @@ class KotlinType extends Element, @kt_type { } class KotlinNullableType extends KotlinType, @kt_nullable_type { override string toString() { - exists(RefType javaType | - kt_nullable_types(this, javaType) and - result = "Kotlin nullable " + javaType.toString() + exists(KotlinType ktType | + kt_nullable_types(this, ktType) and + result = ktType.toString() + "?" ) } override string getAPrimaryQlClass() { result = "KotlinNullableType" } } -class KotlinNotnullType extends KotlinType, @kt_notnull_type { - override string toString() { - exists(RefType javaType | - kt_notnull_types(this, javaType) and - result = "Kotlin not-null " + javaType.toString() - ) - } +class KotlinClassType extends KotlinType, @kt_class_type { + override string toString() { result = this.getClass().toString() } override string getAPrimaryQlClass() { result = "KotlinNotnullType" } + + RefType getClass() { kt_class_types(this, result) } } -class KotlinTypeAlias extends Element, @kt_type_alias { +class KotlinTypeAlias extends KotlinType, @kt_type_alias { override string getAPrimaryQlClass() { result = "KotlinTypeAlias" } - KotlinType getKotlinType() { kt_type_alias(this, _, result) } + override string toString() { + result = "{" + this.getKotlinType().toString() + "}" + this.getName() + } + + override string getName() { result = this.getAliasClass().getName() } + + Class getAliasClass() { kt_type_aliases(this, result, _) } + + KotlinType getKotlinType() { kt_type_aliases(this, _, result) } }