mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
Kotlin: Refactor TypeResults
We statically know when we expect to have no signature, so now we tell the type system what we know, rather than having signature always be nullable.
This commit is contained in:
@@ -848,7 +848,7 @@ open class KotlinFileExtractor(
|
||||
paramTypes
|
||||
}
|
||||
|
||||
val paramsSignature = allParamTypes.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature!! }
|
||||
val paramsSignature = allParamTypes.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature }
|
||||
|
||||
val adjustedReturnType = addJavaLoweringWildcards(getAdjustedReturnType(f), false, (javaCallable as? JavaMethod)?.returnType)
|
||||
val substReturnType = typeSubstitution?.let { it(adjustedReturnType, TypeContext.RETURN, pluginContext) } ?: adjustedReturnType
|
||||
@@ -3866,7 +3866,7 @@ open class KotlinFileExtractor(
|
||||
Pair(paramId, paramType)
|
||||
}
|
||||
|
||||
val paramsSignature = parameters.joinToString(separator = ",", prefix = "(", postfix = ")") { it.second.javaResult.signature!! }
|
||||
val paramsSignature = parameters.joinToString(separator = ",", prefix = "(", postfix = ")") { it.second.javaResult.signature }
|
||||
|
||||
val rt = useType(returnType, TypeContext.RETURN)
|
||||
tw.writeMethods(methodId, name, "$name$paramsSignature", rt.javaResult.id, parentId, methodId)
|
||||
@@ -4041,7 +4041,7 @@ open class KotlinFileExtractor(
|
||||
/**
|
||||
* Extracts a single wildcard type access expression with no enclosing callable and statement.
|
||||
*/
|
||||
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
|
||||
private fun extractWildcardTypeAccess(type: TypeResultsWithoutSignatures, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
|
||||
val id = tw.getFreshIdLabel<DbWildcardtypeaccess>()
|
||||
tw.writeExprs_wildcardtypeaccess(id, type.javaResult.id, parent, idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
@@ -4079,7 +4079,7 @@ open class KotlinFileExtractor(
|
||||
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
|
||||
*/
|
||||
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
|
||||
val typeLabels by lazy { TypeResults(getTypeArgumentLabel(t), TypeResult(fakeKotlinType(), "TODO", "TODO")) }
|
||||
val typeLabels by lazy { TypeResultsWithoutSignatures(getTypeArgumentLabel(t), TypeResultWithoutSignature(fakeKotlinType(), Unit, "TODO")) }
|
||||
when (t) {
|
||||
is IrStarProjection -> extractWildcardTypeAccess(typeLabels, location, parent, idx)
|
||||
is IrTypeProjection -> when(t.variance) {
|
||||
|
||||
@@ -91,25 +91,6 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
|
||||
data class UseClassInstanceResult(val typeResult: TypeResult<DbClassorinterface>, val javaClass: IrClass)
|
||||
/**
|
||||
* A triple of a type's database label, its signature for use in callable signatures, and its short name for use
|
||||
* in all tables that provide a user-facing type name.
|
||||
*
|
||||
* `signature` is a Java primitive name (e.g. "int"), a fully-qualified class name ("package.OuterClass.InnerClass"),
|
||||
* or an array ("componentSignature[]")
|
||||
* Type variables have the signature of their upper bound.
|
||||
* Type arguments and anonymous types do not have a signature.
|
||||
*
|
||||
* `shortName` is a Java primitive name (e.g. "int"), a class short name with Java-style type arguments ("InnerClass<E>" or
|
||||
* "OuterClass<ConcreteArgument>" or "OtherClass<? extends Bound>") or an array ("componentShortName[]").
|
||||
*/
|
||||
data class TypeResult<out LabelType>(val id: Label<out LabelType>, val signature: String?, val shortName: String) {
|
||||
fun <U> cast(): TypeResult<U> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this as TypeResult<U>
|
||||
}
|
||||
}
|
||||
data class TypeResults(val javaResult: TypeResult<DbType>, val kotlinResult: TypeResult<DbKt_type>)
|
||||
|
||||
fun useType(t: IrType, context: TypeContext = TypeContext.OTHER): TypeResults {
|
||||
when(t) {
|
||||
@@ -125,7 +106,7 @@ open class KotlinUsesExtractor(
|
||||
val typeId = tw.getLabelFor<DbErrortype>("@\"errorType\"") {
|
||||
tw.writeError_type(it)
|
||||
}
|
||||
return TypeResult(typeId, null, "<CodeQL error type>")
|
||||
return TypeResult(typeId, "<CodeQL error type>", "<CodeQL error type>")
|
||||
}
|
||||
|
||||
private fun extractErrorType(): TypeResults {
|
||||
@@ -134,7 +115,7 @@ open class KotlinUsesExtractor(
|
||||
tw.writeKt_nullable_types(it, javaResult.id)
|
||||
}
|
||||
return TypeResults(javaResult,
|
||||
TypeResult(kotlinTypeId, null, "<CodeQL error type>"))
|
||||
TypeResult(kotlinTypeId, "<CodeQL error type>", "<CodeQL error type>"))
|
||||
}
|
||||
|
||||
fun getJavaEquivalentClass(c: IrClass) =
|
||||
@@ -431,9 +412,17 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
val fqName = replacedClass.fqNameWhenAvailable
|
||||
val signature = if (fqName == null) {
|
||||
logger.error("Unable to find signature/fqName for ${replacedClass.name}")
|
||||
// TODO: Should we return null here instead?
|
||||
"<no signature available>"
|
||||
} else {
|
||||
fqName.asString()
|
||||
}
|
||||
return TypeResult(
|
||||
classLabel,
|
||||
replacedClass.fqNameWhenAvailable?.asString(),
|
||||
signature,
|
||||
classLabelResult.shortName)
|
||||
}
|
||||
|
||||
@@ -1255,7 +1244,7 @@ open class KotlinUsesExtractor(
|
||||
|
||||
fun getTypeArgumentLabel(
|
||||
arg: IrTypeArgument
|
||||
): TypeResult<DbReftype> {
|
||||
): TypeResultWithoutSignature<DbReftype> {
|
||||
|
||||
fun extractBoundedWildcard(wildcardKind: Int, wildcardLabelStr: String, wildcardShortName: String, boundLabel: Label<out DbReftype>): Label<DbWildcard> =
|
||||
tw.getLabelFor(wildcardLabelStr) { wildcardLabel ->
|
||||
@@ -1270,27 +1259,27 @@ open class KotlinUsesExtractor(
|
||||
return when (arg) {
|
||||
is IrStarProjection -> {
|
||||
val anyTypeLabel = useType(pluginContext.irBuiltIns.anyType).javaResult.id.cast<DbReftype>()
|
||||
TypeResult(extractBoundedWildcard(1, "@\"wildcard;\"", "?", anyTypeLabel), null, "?")
|
||||
TypeResultWithoutSignature(extractBoundedWildcard(1, "@\"wildcard;\"", "?", anyTypeLabel), Unit, "?")
|
||||
}
|
||||
is IrTypeProjection -> {
|
||||
val boundResults = useType(arg.type, TypeContext.GENERIC_ARGUMENT)
|
||||
val boundLabel = boundResults.javaResult.id.cast<DbReftype>()
|
||||
|
||||
return if(arg.variance == Variance.INVARIANT)
|
||||
boundResults.javaResult.cast<DbReftype>()
|
||||
boundResults.javaResult.cast<DbReftype>().forgetSignature()
|
||||
else {
|
||||
val keyPrefix = if (arg.variance == Variance.IN_VARIANCE) "super" else "extends"
|
||||
val wildcardKind = if (arg.variance == Variance.IN_VARIANCE) 2 else 1
|
||||
val wildcardShortName = "? $keyPrefix ${boundResults.javaResult.shortName}"
|
||||
TypeResult(
|
||||
TypeResultWithoutSignature(
|
||||
extractBoundedWildcard(wildcardKind, "@\"wildcard;$keyPrefix{$boundLabel}\"", wildcardShortName, boundLabel),
|
||||
null,
|
||||
Unit,
|
||||
wildcardShortName)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
logger.error("Unexpected type argument.")
|
||||
return extractJavaErrorType()
|
||||
return extractJavaErrorType().forgetSignature()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.github.codeql
|
||||
|
||||
import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels
|
||||
import com.github.codeql.KotlinUsesExtractor.TypeResults
|
||||
import com.github.codeql.utils.versions.FileEntry
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
|
||||
30
java/kotlin-extractor/src/main/kotlin/utils/TypeResults.kt
Normal file
30
java/kotlin-extractor/src/main/kotlin/utils/TypeResults.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.github.codeql
|
||||
|
||||
/**
|
||||
* A triple of a type's database label, its signature for use in callable signatures, and its short name for use
|
||||
* in all tables that provide a user-facing type name.
|
||||
*
|
||||
* `signature` is a Java primitive name (e.g. "int"), a fully-qualified class name ("package.OuterClass.InnerClass"),
|
||||
* or an array ("componentSignature[]")
|
||||
* Type variables have the signature of their upper bound.
|
||||
* Type arguments and anonymous types do not have a signature.
|
||||
*
|
||||
* `shortName` is a Java primitive name (e.g. "int"), a class short name with Java-style type arguments ("InnerClass<E>" or
|
||||
* "OuterClass<ConcreteArgument>" or "OtherClass<? extends Bound>") or an array ("componentShortName[]").
|
||||
*/
|
||||
data class TypeResultGeneric<SignatureType,out LabelType>(val id: Label<out LabelType>, val signature: SignatureType, val shortName: String) {
|
||||
fun <U> cast(): TypeResult<U> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this as TypeResult<U>
|
||||
}
|
||||
}
|
||||
data class TypeResultsGeneric<SignatureType>(val javaResult: TypeResultGeneric<SignatureType,DbType>, val kotlinResult: TypeResultGeneric<SignatureType,DbKt_type>)
|
||||
|
||||
typealias TypeResult<T> = TypeResultGeneric<String,T>
|
||||
typealias TypeResultWithoutSignature<T> = TypeResultGeneric<Unit,T>
|
||||
typealias TypeResults = TypeResultsGeneric<String>
|
||||
typealias TypeResultsWithoutSignatures = TypeResultsGeneric<Unit>
|
||||
|
||||
fun <T> TypeResult<T>.forgetSignature(): TypeResultWithoutSignature<T> {
|
||||
return TypeResultWithoutSignature(this.id, Unit, this.shortName)
|
||||
}
|
||||
Reference in New Issue
Block a user