mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge branch 'main' into post-release-prep/codeql-cli-2.10.0
This commit is contained in:
@@ -35,8 +35,8 @@ sourceSets {
|
||||
"utils/versions/v_1_5_21/*.kt",
|
||||
"utils/versions/v_1_5_31/*.kt",
|
||||
"utils/versions/v_1_6_10/*.kt",
|
||||
"utils/versions/v_1_7_0-RC/*.kt",
|
||||
// "utils/versions/v_1_6_20/*.kt",
|
||||
"utils/versions/v_1_6_20/*.kt",
|
||||
// "utils/versions/v_1_7_0/*.kt",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
kotlin.code.style=official
|
||||
kotlinVersion=1.6.20
|
||||
kotlinVersion=1.7.0
|
||||
|
||||
GROUP=com.github.codeql
|
||||
VERSION_NAME=0.0.1
|
||||
|
||||
@@ -21,7 +21,7 @@ def version_string_to_tuple(version):
|
||||
m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)(.*)', version)
|
||||
return tuple([int(m.group(i)) for i in range(1, 4)] + [m.group(4)])
|
||||
|
||||
many_versions = [ '1.4.32', '1.5.0', '1.5.10', '1.5.21', '1.5.31', '1.6.10', '1.7.0-RC', '1.6.20' ]
|
||||
many_versions = [ '1.4.32', '1.5.0', '1.5.10', '1.5.21', '1.5.31', '1.6.10', '1.6.20', '1.7.0' ]
|
||||
|
||||
many_versions_tuples = [version_string_to_tuple(v) for v in many_versions]
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ import com.semmle.extractor.java.OdasaOutput
|
||||
import com.semmle.util.data.StringDigestor
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isFileClass
|
||||
import org.jetbrains.kotlin.ir.util.packageFqName
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
@@ -16,18 +18,20 @@ import java.util.zip.GZIPOutputStream
|
||||
|
||||
class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: String, val sourceFilePath: String, val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState, val diagnosticTrapWriter: TrapWriter) {
|
||||
|
||||
val externalDeclsDone = HashSet<IrDeclaration>()
|
||||
val declBinaryNames = HashMap<IrDeclaration, String>()
|
||||
val externalDeclsDone = HashSet<Pair<String, String>>()
|
||||
val externalDeclWorkList = ArrayList<Pair<IrDeclaration, String>>()
|
||||
|
||||
val propertySignature = ";property"
|
||||
val fieldSignature = ";field"
|
||||
|
||||
fun extractLater(d: IrDeclaration, signature: String): Boolean {
|
||||
fun extractLater(d: IrDeclarationWithName, signature: String): Boolean {
|
||||
if (d !is IrClass && !isExternalFileClassMember(d)) {
|
||||
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
|
||||
return false
|
||||
}
|
||||
val ret = externalDeclsDone.add(d)
|
||||
val declBinaryName = declBinaryNames.getOrPut(d) { getIrDeclBinaryName(d) }
|
||||
val ret = externalDeclsDone.add(Pair(declBinaryName, signature))
|
||||
if (ret) externalDeclWorkList.add(Pair(d, signature))
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ open class KotlinFileExtractor(
|
||||
globalExtensionState: KotlinExtractorGlobalState
|
||||
): KotlinUsesExtractor(logger, tw, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState) {
|
||||
|
||||
inline fun <T> with(kind: String, element: IrElement, f: () -> T): T {
|
||||
private inline fun <T> with(kind: String, element: IrElement, f: () -> T): T {
|
||||
val name = when (element) {
|
||||
is IrFile -> element.name
|
||||
is IrDeclarationWithName -> element.name.asString()
|
||||
@@ -86,6 +86,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
private fun isFake(d: IrDeclarationWithVisibility): Boolean {
|
||||
val visibility = d.visibility
|
||||
if (visibility is DelegatedDescriptorVisibility && visibility.delegate == Visibilities.InvisibleFake) {
|
||||
@@ -94,6 +95,9 @@ open class KotlinFileExtractor(
|
||||
if (d.isFakeOverride) {
|
||||
return true
|
||||
}
|
||||
if ((d as? IrFunction)?.descriptor?.isHiddenToOvercomeSignatureClash == true) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -367,6 +371,27 @@ open class KotlinFileExtractor(
|
||||
tw.writeHasLocation(stmtId, locId)
|
||||
}
|
||||
|
||||
fun extractObinitFunction(c: IrClass, parentId: Label<out DbClassorinterface>) {
|
||||
// add method:
|
||||
val obinitLabel = getObinitLabel(c)
|
||||
val obinitId = tw.getLabelFor<DbMethod>(obinitLabel)
|
||||
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
|
||||
tw.writeMethods(obinitId, "<obinit>", "<obinit>()", returnType.javaResult.id, parentId, obinitId)
|
||||
tw.writeMethodsKotlinType(obinitId, returnType.kotlinResult.id)
|
||||
|
||||
val locId = tw.getLocation(c)
|
||||
tw.writeHasLocation(obinitId, locId)
|
||||
|
||||
addModifiers(obinitId, "private")
|
||||
|
||||
// add body:
|
||||
val blockId = tw.getFreshIdLabel<DbBlock>()
|
||||
tw.writeStmts_block(blockId, obinitId, 0, obinitId)
|
||||
tw.writeHasLocation(blockId, locId)
|
||||
|
||||
extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) }
|
||||
}
|
||||
|
||||
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
|
||||
with("class source", c) {
|
||||
DeclarationStackAdjuster(c).use {
|
||||
@@ -421,6 +446,9 @@ open class KotlinFileExtractor(
|
||||
addModifiers(instance.id, "public", "static", "final")
|
||||
tw.writeClass_object(id.cast<DbClass>(), instance.id)
|
||||
}
|
||||
if (extractFunctionBodies && needsObinitFunction(c)) {
|
||||
extractObinitFunction(c, id)
|
||||
}
|
||||
|
||||
extractClassModifiers(c, id)
|
||||
extractClassSupertypes(c, id, inReceiverContext = true) // inReceiverContext = true is specified to force extraction of member prototypes of base types
|
||||
@@ -567,6 +595,8 @@ open class KotlinFileExtractor(
|
||||
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, parentId, clinitId)
|
||||
tw.writeMethodsKotlinType(clinitId, returnType.kotlinResult.id)
|
||||
|
||||
tw.writeCompiler_generated(clinitId, CompilerGeneratedKinds.CLASS_INITIALISATION_METHOD.kind)
|
||||
|
||||
val locId = tw.getWholeFileLocation()
|
||||
tw.writeHasLocation(clinitId, locId)
|
||||
|
||||
@@ -704,12 +734,9 @@ open class KotlinFileExtractor(
|
||||
|
||||
val id =
|
||||
idOverride
|
||||
?: if (f.isLocalFunction())
|
||||
getLocallyVisibleFunctionLabels(f).function
|
||||
else
|
||||
// If this is a class that would ordinarily be replaced by a Java equivalent (e.g. kotlin.Map -> java.util.Map),
|
||||
// don't replace here, really extract the Kotlin version:
|
||||
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses, noReplace = true)
|
||||
?: // If this is a class that would ordinarily be replaced by a Java equivalent (e.g. kotlin.Map -> java.util.Map),
|
||||
// don't replace here, really extract the Kotlin version:
|
||||
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses, noReplace = true)
|
||||
|
||||
val sourceDeclaration =
|
||||
if (typeSubstitution != null && idOverride == null)
|
||||
@@ -755,6 +782,14 @@ open class KotlinFileExtractor(
|
||||
val methodId = id.cast<DbMethod>()
|
||||
tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast<DbMethod>())
|
||||
tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id)
|
||||
when (f.origin) {
|
||||
IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER ->
|
||||
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind)
|
||||
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR ->
|
||||
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind)
|
||||
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER ->
|
||||
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind)
|
||||
}
|
||||
|
||||
if (extractMethodAndParameterTypeAccesses) {
|
||||
extractTypeAccessRecursive(substReturnType, locId, id, -1)
|
||||
@@ -1045,7 +1080,7 @@ open class KotlinFileExtractor(
|
||||
tw.writeKtLocalFunction(ids.function)
|
||||
|
||||
if (s.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
|
||||
tw.writeCompiler_generated(classId, 1)
|
||||
tw.writeCompiler_generated(classId, CompilerGeneratedKinds.DECLARING_CLASSES_OF_ADAPTER_FUNCTIONS.kind)
|
||||
}
|
||||
} else {
|
||||
logger.errorElement("Expected to find local function", s)
|
||||
@@ -2101,6 +2136,22 @@ open class KotlinFileExtractor(
|
||||
enclosingStmt: Label<out DbStmt>
|
||||
): Label<DbNewexpr> = extractNewExpr(useFunction<DbConstructor>(calledConstructor, constructorTypeArgs), constructedType, locId, parent, idx, callable, enclosingStmt)
|
||||
|
||||
private fun needsObinitFunction(c: IrClass) = c.primaryConstructor == null && c.constructors.count() > 1
|
||||
|
||||
private fun getObinitLabel(c: IrClass) = getFunctionLabel(
|
||||
c,
|
||||
null,
|
||||
"<obinit>",
|
||||
listOf(),
|
||||
pluginContext.irBuiltIns.unitType,
|
||||
null,
|
||||
functionTypeParameters = listOf(),
|
||||
classTypeArgsIncludingOuterClasses = listOf(),
|
||||
overridesCollectionsMethod = false,
|
||||
javaSignature = null,
|
||||
addParameterWildcardsByDefault = false
|
||||
)
|
||||
|
||||
private fun extractConstructorCall(
|
||||
e: IrFunctionAccessExpression,
|
||||
parent: Label<out DbExprparent>,
|
||||
@@ -2153,8 +2204,6 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
private val loopIdMap: MutableMap<IrLoop, Label<out DbKtloopstmt>> = mutableMapOf()
|
||||
|
||||
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
|
||||
private val declarationStack: Stack<IrDeclaration> = Stack()
|
||||
|
||||
@@ -2192,7 +2241,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
fun getStatementOriginOperator(origin: IrStatementOrigin?) = when (origin) {
|
||||
private fun getStatementOriginOperator(origin: IrStatementOrigin?) = when (origin) {
|
||||
IrStatementOrigin.PLUSEQ -> "plus"
|
||||
IrStatementOrigin.MINUSEQ -> "minus"
|
||||
IrStatementOrigin.MULTEQ -> "times"
|
||||
@@ -2402,41 +2451,35 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
is IrWhileLoop -> {
|
||||
val stmtParent = parent.stmt(e, callable)
|
||||
val id = tw.getFreshIdLabel<DbWhilestmt>()
|
||||
loopIdMap[e] = id
|
||||
val locId = tw.getLocation(e)
|
||||
tw.writeStmts_whilestmt(id, stmtParent.parent, stmtParent.idx, callable)
|
||||
tw.writeHasLocation(id, locId)
|
||||
extractExpressionExpr(e.condition, callable, id, 0, id)
|
||||
val body = e.body
|
||||
if(body != null) {
|
||||
extractExpressionStmt(body, callable, id, 1)
|
||||
}
|
||||
loopIdMap.remove(e)
|
||||
extractLoop(e, parent, callable)
|
||||
}
|
||||
is IrDoWhileLoop -> {
|
||||
val stmtParent = parent.stmt(e, callable)
|
||||
val id = tw.getFreshIdLabel<DbDostmt>()
|
||||
loopIdMap[e] = id
|
||||
val locId = tw.getLocation(e)
|
||||
tw.writeStmts_dostmt(id, stmtParent.parent, stmtParent.idx, callable)
|
||||
tw.writeHasLocation(id, locId)
|
||||
extractExpressionExpr(e.condition, callable, id, 0, id)
|
||||
val body = e.body
|
||||
if(body != null) {
|
||||
extractExpressionStmt(body, callable, id, 1)
|
||||
}
|
||||
loopIdMap.remove(e)
|
||||
extractLoop(e, parent, callable)
|
||||
}
|
||||
is IrInstanceInitializerCall -> {
|
||||
val stmtParent = parent.stmt(e, callable)
|
||||
val irConstructor = declarationStack.peek() as? IrConstructor
|
||||
if (irConstructor == null) {
|
||||
logger.errorElement("IrInstanceInitializerCall outside constructor", e)
|
||||
return
|
||||
}
|
||||
extractInstanceInitializerBlock(stmtParent, irConstructor)
|
||||
if (needsObinitFunction(irConstructor.parentAsClass)) {
|
||||
val exprParent = parent.expr(e, callable)
|
||||
val id = tw.getFreshIdLabel<DbMethodaccess>()
|
||||
val type = useType(pluginContext.irBuiltIns.unitType)
|
||||
val locId = tw.getLocation(e)
|
||||
val methodLabel = getObinitLabel(irConstructor.parentAsClass)
|
||||
val methodId = tw.getLabelFor<DbMethod>(methodLabel)
|
||||
tw.writeExprs_methodaccess(id, type.javaResult.id, exprParent.parent, exprParent.idx)
|
||||
tw.writeExprsKotlinType(id, type.kotlinResult.id)
|
||||
tw.writeHasLocation(id, locId)
|
||||
tw.writeCallableEnclosingExpr(id, callable)
|
||||
tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt)
|
||||
tw.writeCallableBinding(id, methodId)
|
||||
}
|
||||
else {
|
||||
val stmtParent = parent.stmt(e, callable)
|
||||
extractInstanceInitializerBlock(stmtParent, irConstructor)
|
||||
}
|
||||
}
|
||||
is IrConstructorCall -> {
|
||||
val exprParent = parent.expr(e, callable)
|
||||
@@ -2928,6 +2971,49 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractLoop(
|
||||
loop: IrLoop,
|
||||
stmtExprParent: StmtExprParent,
|
||||
callable: Label<out DbCallable>
|
||||
) {
|
||||
val stmtParent = stmtExprParent.stmt(loop, callable)
|
||||
val locId = tw.getLocation(loop)
|
||||
|
||||
val idx: Int
|
||||
val parent: Label<out DbStmtparent>
|
||||
|
||||
val label = loop.label
|
||||
if (label != null) {
|
||||
val labeledStmt = tw.getFreshIdLabel<DbLabeledstmt>()
|
||||
tw.writeStmts_labeledstmt(labeledStmt, stmtParent.parent, stmtParent.idx, callable)
|
||||
tw.writeHasLocation(labeledStmt, locId)
|
||||
|
||||
tw.writeNamestrings(label, "", labeledStmt)
|
||||
idx = 0
|
||||
parent = labeledStmt
|
||||
} else {
|
||||
idx = stmtParent.idx
|
||||
parent = stmtParent.parent
|
||||
}
|
||||
|
||||
val id = if (loop is IrWhileLoop) {
|
||||
val id = tw.getFreshIdLabel<DbWhilestmt>()
|
||||
tw.writeStmts_whilestmt(id, parent, idx, callable)
|
||||
id
|
||||
} else {
|
||||
val id = tw.getFreshIdLabel<DbDostmt>()
|
||||
tw.writeStmts_dostmt(id, parent, idx, callable)
|
||||
id
|
||||
}
|
||||
|
||||
tw.writeHasLocation(id, locId)
|
||||
extractExpressionExpr(loop.condition, callable, id, 0, id)
|
||||
val body = loop.body
|
||||
if (body != null) {
|
||||
extractExpressionStmt(body, callable, id, 1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrValueParameter.isExtensionReceiver(): Boolean {
|
||||
val parentFun = parent as? IrFunction ?: return false
|
||||
return parentFun.extensionReceiverParameter == this
|
||||
@@ -4201,7 +4287,7 @@ open class KotlinFileExtractor(
|
||||
|
||||
private fun extractBreakContinue(
|
||||
e: IrBreakContinue,
|
||||
id: Label<out DbBreakcontinuestmt>
|
||||
id: Label<out DbNamedexprorstmt>
|
||||
) {
|
||||
with("break/continue", e) {
|
||||
val locId = tw.getLocation(e)
|
||||
@@ -4210,14 +4296,6 @@ open class KotlinFileExtractor(
|
||||
if (label != null) {
|
||||
tw.writeNamestrings(label, "", id)
|
||||
}
|
||||
|
||||
val loopId = loopIdMap[e.loop]
|
||||
if (loopId == null) {
|
||||
logger.errorElement("Missing break/continue target", e)
|
||||
return
|
||||
}
|
||||
|
||||
tw.writeKtBreakContinueTargets(id, loopId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4299,4 +4377,12 @@ open class KotlinFileExtractor(
|
||||
declarationStack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
private enum class CompilerGeneratedKinds(val kind: Int) {
|
||||
DECLARING_CLASSES_OF_ADAPTER_FUNCTIONS(1),
|
||||
GENERATED_DATA_CLASS_MEMBER(2),
|
||||
DEFAULT_PROPERTY_ACCESSOR(3),
|
||||
CLASS_INITIALISATION_METHOD(4),
|
||||
ENUM_CLASS_SPECIAL_MEMBER(5)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
|
||||
// The Kotlin compiler internal representation of Outer<A, B>.Inner<C, D>.InnerInner<E, F>.someFunction<G, H>.LocalClass<I, J> is LocalClass<I, J, G, H, E, F, C, D, A, B>. This function returns [A, B, C, D, E, F, G, H, I, J].
|
||||
fun orderTypeArgsLeftToRight(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): List<IrTypeArgument>? {
|
||||
private fun orderTypeArgsLeftToRight(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): List<IrTypeArgument>? {
|
||||
if(argsIncludingOuterClasses.isNullOrEmpty())
|
||||
return argsIncludingOuterClasses
|
||||
val ret = ArrayList<IrTypeArgument>()
|
||||
@@ -237,7 +237,7 @@ open class KotlinUsesExtractor(
|
||||
return UseClassInstanceResult(classTypeResult, extractClass)
|
||||
}
|
||||
|
||||
fun isArray(t: IrSimpleType) = t.isBoxedArray || t.isPrimitiveArray()
|
||||
private fun isArray(t: IrSimpleType) = t.isBoxedArray || t.isPrimitiveArray()
|
||||
|
||||
fun extractClassLaterIfExternal(c: IrClass) {
|
||||
if (isExternalDeclaration(c)) {
|
||||
@@ -1146,15 +1146,6 @@ open class KotlinUsesExtractor(
|
||||
return res
|
||||
}
|
||||
|
||||
fun <T: DbCallable> useFunctionCommon(f: IrFunction, label: String): Label<out T> {
|
||||
val id: Label<T> = tw.getLabelFor(label)
|
||||
if (isExternalDeclaration(f)) {
|
||||
extractFunctionLaterIfExternalFileMember(f)
|
||||
extractExternalEnclosingClassLater(f)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// These are classes with Java equivalents, but whose methods don't all exist on those Java equivalents--
|
||||
// for example, the numeric classes define arithmetic functions (Int.plus, Long.or and so on) that lower to
|
||||
// primitive arithmetic on the JVM, but which we extract as calls to reflect the source syntax more closely.
|
||||
@@ -1210,20 +1201,24 @@ open class KotlinUsesExtractor(
|
||||
} as IrFunction? ?: f
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
|
||||
return useFunction(f, null, classTypeArgsIncludingOuterClasses, noReplace)
|
||||
}
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
|
||||
if (f.isLocalFunction()) {
|
||||
val ids = getLocallyVisibleFunctionLabels(f)
|
||||
return ids.function.cast<T>()
|
||||
} else {
|
||||
val realFunction = kotlinFunctionToJavaEquivalent(f, noReplace)
|
||||
return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses))
|
||||
}
|
||||
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
|
||||
val label = getFunctionLabel(javaFun, parentId, classTypeArgsIncludingOuterClasses)
|
||||
val id: Label<T> = tw.getLabelFor(label)
|
||||
if (isExternalDeclaration(javaFun)) {
|
||||
extractFunctionLaterIfExternalFileMember(javaFun)
|
||||
extractExternalEnclosingClassLater(javaFun)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false) =
|
||||
kotlinFunctionToJavaEquivalent(f, noReplace).let {
|
||||
useFunctionCommon<T>(it, getFunctionLabel(it, parentId, classTypeArgsIncludingOuterClasses))
|
||||
}
|
||||
|
||||
fun getTypeArgumentLabel(
|
||||
arg: IrTypeArgument
|
||||
): TypeResult<DbReftype> {
|
||||
@@ -1464,7 +1459,7 @@ open class KotlinUsesExtractor(
|
||||
return t
|
||||
}
|
||||
|
||||
fun eraseTypeParameter(t: IrTypeParameter) =
|
||||
private fun eraseTypeParameter(t: IrTypeParameter) =
|
||||
erase(t.superTypes[0])
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
package com.github.codeql
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IdSignatureValues
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContext) {
|
||||
fun getPrimitiveInfo(s: IrSimpleType) = mapping[s.classifier.signature]
|
||||
fun getPrimitiveInfo(s: IrSimpleType) =
|
||||
s.classOrNull?.let {
|
||||
if ((it.owner.parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
mapping[it.owner.name]
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
data class PrimitiveTypeInfo(
|
||||
val primitiveName: String?,
|
||||
@@ -60,25 +67,25 @@ class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContex
|
||||
val javaLangVoid = findClass("java.lang.Void", kotlinNothing)
|
||||
|
||||
mapOf(
|
||||
IdSignatureValues._byte to PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
|
||||
IdSignatureValues._short to PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
|
||||
IdSignatureValues._int to PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
|
||||
IdSignatureValues._long to PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
|
||||
StandardNames.FqNames._byte.shortName() to PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
|
||||
StandardNames.FqNames._short.shortName() to PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
|
||||
StandardNames.FqNames._int.shortName() to PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
|
||||
StandardNames.FqNames._long.shortName() to PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
|
||||
|
||||
IdSignatureValues.uByte to PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
|
||||
IdSignatureValues.uShort to PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
|
||||
IdSignatureValues.uInt to PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
|
||||
IdSignatureValues.uLong to PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
|
||||
StandardNames.FqNames.uByteFqName.shortName() to PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
|
||||
StandardNames.FqNames.uShortFqName.shortName() to PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
|
||||
StandardNames.FqNames.uIntFqName.shortName() to PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
|
||||
StandardNames.FqNames.uLongFqName.shortName() to PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
|
||||
|
||||
IdSignatureValues._double to PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
|
||||
IdSignatureValues._float to PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
|
||||
StandardNames.FqNames._double.shortName() to PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
|
||||
StandardNames.FqNames._float.shortName() to PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
|
||||
|
||||
IdSignatureValues._boolean to PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
|
||||
StandardNames.FqNames._boolean.shortName() to PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
|
||||
|
||||
IdSignatureValues._char to PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
|
||||
StandardNames.FqNames._char.shortName() to PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
|
||||
|
||||
IdSignatureValues.unit to PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
|
||||
IdSignatureValues.nothing to PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
|
||||
StandardNames.FqNames.unit.shortName() to PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
|
||||
StandardNames.FqNames.nothing.shortName() to PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
|
||||
)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -40,4 +40,4 @@ fun AutoCloseable?.closeFinallyAC(cause: Throwable?) = when {
|
||||
} catch (closeException: Throwable) {
|
||||
cause.addSuppressed(closeException)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,20 +207,6 @@ open class LoggerBase(val logCounter: LogCounter) {
|
||||
}
|
||||
|
||||
open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
|
||||
private fun getDiagnosticLocation(): String? {
|
||||
val st = Exception().stackTrace
|
||||
for(x in st) {
|
||||
when(x.className) {
|
||||
"com.github.codeql.Logger",
|
||||
"com.github.codeql.FileLogger" -> {}
|
||||
else -> {
|
||||
return x.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun flush() {
|
||||
tw.flush()
|
||||
loggerBase.flush()
|
||||
@@ -240,7 +226,7 @@ open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
|
||||
loggerBase.info(tw, msg)
|
||||
}
|
||||
|
||||
fun warn(msg: String, extraInfo: String?) {
|
||||
private fun warn(msg: String, extraInfo: String?) {
|
||||
loggerBase.warn(tw, msg, extraInfo)
|
||||
}
|
||||
fun warn(msg: String, exn: Throwable) {
|
||||
@@ -250,7 +236,7 @@ open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
|
||||
warn(msg, null)
|
||||
}
|
||||
|
||||
fun error(msg: String, extraInfo: String?) {
|
||||
private fun error(msg: String, extraInfo: String?) {
|
||||
loggerBase.error(tw, msg, extraInfo)
|
||||
}
|
||||
fun error(msg: String) {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import com.github.codeql.KotlinUsesExtractor
|
||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||
|
||||
fun <TIrStub> KotlinUsesExtractor.getIrStubFromDescriptor(generateStub: (DeclarationStubGenerator) -> TIrStub) : TIrStub? {
|
||||
logger.error("Descriptors not yet supported for Kotlin 1.7")
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import com.github.codeql.KotlinUsesExtractor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
|
||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun <TIrStub> KotlinUsesExtractor.getIrStubFromDescriptor(generateStub: (DeclarationStubGenerator) -> TIrStub) : TIrStub? =
|
||||
(pluginContext.symbolTable as? SymbolTable) ?.let {
|
||||
// Copying the construction seen in JvmIrLinker.kt
|
||||
val mangler = JvmDescriptorMangler(MainFunctionDetector(pluginContext.bindingContext, pluginContext.languageVersionSettings))
|
||||
val descriptorFinder = DescriptorByIdSignatureFinderImpl(
|
||||
pluginContext.moduleDescriptor,
|
||||
mangler,
|
||||
DescriptorByIdSignatureFinderImpl.LookupMode.MODULE_ONLY
|
||||
)
|
||||
val stubGenerator = DeclarationStubGeneratorImpl(pluginContext.moduleDescriptor, it, pluginContext.irBuiltIns, descriptorFinder)
|
||||
generateStub(stubGenerator)
|
||||
} ?: run {
|
||||
logger.error("Plugin context has no symbol table, couldn't get IR stub")
|
||||
null
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
where not exists(ma.getQualifier()) and ma.getFile().isKotlinSourceFile()
|
||||
// Generally Kotlin calls will always use an explicit qualifier, except for calls
|
||||
// to the synthetic instance initializer <obinit>, which use an implicit `this`.
|
||||
where
|
||||
not exists(ma.getQualifier()) and
|
||||
ma.getFile().isKotlinSourceFile() and
|
||||
not ma.getCallee() instanceof InstanceInitializer
|
||||
select ma
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
a.kt:
|
||||
# 0| [CompilationUnit] a
|
||||
# 1| 1: [Class] A
|
||||
# 0| 1: [Method] <fn>
|
||||
# 0| 3: [TypeAccess] int
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [IntegerLiteral] 42
|
||||
# 1| 2: [Constructor] A
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
# 2| 3: [Method] f1
|
||||
# 2| 3: [TypeAccess] int
|
||||
# 2| 5: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 2| 0: [IntegerLiteral] 1
|
||||
b.kt:
|
||||
# 0| [CompilationUnit] b
|
||||
# 1| 1: [Class] B
|
||||
# 0| 1: [Method] <fn>
|
||||
# 0| 3: [TypeAccess] int
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [UnsafeCoerceExpr] <unsafe coerce>
|
||||
# 0| 0: [TypeAccess] int
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 1| 2: [Constructor] B
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
c.kt:
|
||||
# 0| [CompilationUnit] c
|
||||
# 1| 1: [Class] C
|
||||
# 0| 1: [Method] <fn>
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] param
|
||||
# 0| 0: [TypeAccess] ProcessBuilder
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] start(...)
|
||||
# 0| -1: [VarAccess] param
|
||||
# 1| 2: [Constructor] C
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
d.kt:
|
||||
# 0| [CompilationUnit] d
|
||||
# 1| 1: [Class] D
|
||||
# 0| 1: [FieldDeclaration] String bar;
|
||||
# 0| -1: [TypeAccess] String
|
||||
# 0| 0: [StringLiteral] Foobar
|
||||
# 1| 3: [Constructor] D
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
e.kt:
|
||||
# 0| [CompilationUnit] e
|
||||
# 1| 1: [Class] E
|
||||
# 0| 1: [Method] <fn_ArrayListAdd>
|
||||
# 0| 3: [TypeAccess] boolean
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] add(...)
|
||||
# 0| -1: [ClassInstanceExpr] new ArrayList<Object>(...)
|
||||
# 0| -3: [TypeAccess] ArrayList<Object>
|
||||
# 0| 0: [IntegerLiteral] 1
|
||||
# 0| 0: [NullLiteral] null
|
||||
# 0| 1: [Method] <fn_LinkedHashMap>
|
||||
# 0| 3: [TypeAccess] Object
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] put(...)
|
||||
# 0| -1: [ClassInstanceExpr] new LinkedHashMap<Object,Object>(...)
|
||||
# 0| -3: [TypeAccess] LinkedHashMap<Object,Object>
|
||||
# 0| 0: [IntegerLiteral] 1
|
||||
# 0| 0: [NullLiteral] null
|
||||
# 0| 1: [NullLiteral] null
|
||||
# 1| 3: [Constructor] E
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
fun f1() = 1
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
class B {
|
||||
}
|
||||
53
java/ql/integration-tests/linux-only/kotlin/custom_plugin/build_plugin
Executable file
53
java/ql/integration-tests/linux-only/kotlin/custom_plugin/build_plugin
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import shutil
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import shlex
|
||||
|
||||
|
||||
def run_process(cmd):
|
||||
try:
|
||||
print("Running command: " + shlex.join(cmd))
|
||||
return subprocess.run(cmd, check=True, capture_output=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("In: " + os.getcwd(), file=sys.stderr)
|
||||
print("Command failed: " + shlex.join(cmd), file=sys.stderr)
|
||||
print("stdout output:\n" + e.stdout.decode(encoding='UTF-8',
|
||||
errors='strict'), file=sys.stderr)
|
||||
print("stderr output:\n" + e.stderr.decode(encoding='UTF-8',
|
||||
errors='strict'), file=sys.stderr)
|
||||
raise e
|
||||
|
||||
root = '../../../../../../../../..'
|
||||
|
||||
sys.path.append(root + '/ql/java/kotlin-extractor')
|
||||
import kotlin_plugin_versions
|
||||
defaultKotlinDependencyVersion = kotlin_plugin_versions.get_single_version()
|
||||
|
||||
builddir = 'build'
|
||||
dependency_dir = root + '/resources/kotlin-dependencies/'
|
||||
dependencies = ['kotlin-stdlib-' + defaultKotlinDependencyVersion +
|
||||
'.jar', 'kotlin-compiler-' + defaultKotlinDependencyVersion + '.jar']
|
||||
classpath = ':'.join([dependency_dir + dep for dep in dependencies])
|
||||
srcs = ['plugin/Plugin.kt']
|
||||
output = 'plugin.jar'
|
||||
|
||||
if os.path.exists(builddir):
|
||||
shutil.rmtree(builddir)
|
||||
os.makedirs(builddir)
|
||||
|
||||
run_process(['kotlinc',
|
||||
'-J-Xmx2G',
|
||||
'-d', builddir,
|
||||
'-module-name', 'test',
|
||||
'-no-reflect', '-no-stdlib',
|
||||
'-jvm-target', '1.8',
|
||||
'-classpath', classpath] + srcs)
|
||||
|
||||
run_process(['jar', '-c', '-f', output,
|
||||
'-C', builddir, '.',
|
||||
'-C', 'plugin/resources', 'META-INF'])
|
||||
shutil.rmtree(builddir)
|
||||
@@ -0,0 +1 @@
|
||||
class C { }
|
||||
@@ -0,0 +1 @@
|
||||
class D { }
|
||||
@@ -0,0 +1,2 @@
|
||||
| CodeQL Kotlin extractor | 2 | | IrProperty without a getter | d.kt:0:0:0:0 | d.kt:0:0:0:0 |
|
||||
| CodeQL Kotlin extractor | 2 | | Not rewriting trap file for: Boolean -1.0-0- -1.0-0-null test-db/trap/java/classes/kotlin/Boolean.members.trap.gz | file://:0:0:0:0 | file://:0:0:0:0 |
|
||||
13
java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql
Executable file
13
java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql
Executable file
@@ -0,0 +1,13 @@
|
||||
import java
|
||||
|
||||
from string genBy, int severity, string tag, string msg, Location l
|
||||
where
|
||||
diagnostics(_, genBy, severity, tag, msg, _, l) and
|
||||
(
|
||||
// Different installations get different sets of these messages,
|
||||
// so we filter out all but one that happens everywhere.
|
||||
msg.matches("Not rewriting trap file for: %")
|
||||
implies
|
||||
msg.matches("Not rewriting trap file for: Boolean %")
|
||||
)
|
||||
select genBy, severity, tag, msg, l
|
||||
@@ -0,0 +1 @@
|
||||
class E { }
|
||||
@@ -0,0 +1,7 @@
|
||||
| a.kt:0:0:0:0 | <fn> | has body |
|
||||
| a.kt:2:5:2:16 | f1 | has body |
|
||||
| b.kt:0:0:0:0 | <fn> | has body |
|
||||
| c.kt:0:0:0:0 | <fn> | has body |
|
||||
| d.kt:0:0:0:0 | <clinit> | has body |
|
||||
| e.kt:0:0:0:0 | <fn_ArrayListAdd> | has body |
|
||||
| e.kt:0:0:0:0 | <fn_LinkedHashMap> | has body |
|
||||
7
java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql
Executable file
7
java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql
Executable file
@@ -0,0 +1,7 @@
|
||||
import java
|
||||
|
||||
from Method m, string body
|
||||
where
|
||||
m.fromSource() and
|
||||
if exists(m.getBody()) then body = "has body" else body = "has no body"
|
||||
select m, body
|
||||
@@ -0,0 +1,280 @@
|
||||
package com.github.codeql
|
||||
|
||||
import com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irExprBody
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TestComponentRegistrar : ComponentRegistrar {
|
||||
override fun registerProjectComponents(
|
||||
project: MockProject,
|
||||
configuration: CompilerConfiguration
|
||||
) {
|
||||
IrGenerationExtension.registerExtension(project, IrAdder())
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class IrAdder : IrGenerationExtension {
|
||||
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
|
||||
|
||||
class AndroidSymbols {
|
||||
private val irFactory: IrFactory = IrFactoryImpl
|
||||
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage("kotlin.jvm.internal")
|
||||
private val javaUtil: IrPackageFragment = createPackage("java.util")
|
||||
|
||||
private fun createPackage(packageName: String): IrPackageFragment =
|
||||
IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(
|
||||
moduleFragment.descriptor,
|
||||
FqName(packageName)
|
||||
)
|
||||
|
||||
private fun createClass(
|
||||
irPackage: IrPackageFragment,
|
||||
shortName: String,
|
||||
classKind: ClassKind,
|
||||
classModality: Modality
|
||||
): IrClassSymbol = irFactory.buildClass {
|
||||
name = Name.identifier(shortName)
|
||||
kind = classKind
|
||||
modality = classModality
|
||||
}.apply {
|
||||
parent = irPackage
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
}.symbol
|
||||
|
||||
val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol =
|
||||
irFactory.buildFun {
|
||||
name = Name.special("<unsafe-coerce>")
|
||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
}.apply {
|
||||
parent = kotlinJvmInternalPackage
|
||||
val src = addTypeParameter("T", pluginContext.irBuiltIns.anyNType)
|
||||
val dst = addTypeParameter("R", pluginContext.irBuiltIns.anyNType)
|
||||
addValueParameter("v", src.defaultType)
|
||||
returnType = dst.defaultType
|
||||
}.symbol
|
||||
|
||||
val javaUtilArrayList: IrClassSymbol =
|
||||
createClass(javaUtil, "ArrayList", ClassKind.CLASS, Modality.OPEN)
|
||||
|
||||
val javaUtilLinkedHashMap: IrClassSymbol =
|
||||
createClass(javaUtil, "LinkedHashMap", ClassKind.CLASS, Modality.OPEN)
|
||||
|
||||
val arrayListConstructor: IrConstructorSymbol = javaUtilArrayList.owner.addConstructor().apply {
|
||||
addValueParameter("p_0", pluginContext.irBuiltIns.intType)
|
||||
}.symbol
|
||||
|
||||
val arrayListAdd: IrSimpleFunctionSymbol =
|
||||
javaUtilArrayList.owner.addFunction("add", pluginContext.irBuiltIns.booleanType).apply {
|
||||
addValueParameter("p_0", pluginContext.irBuiltIns.anyNType)
|
||||
}.symbol
|
||||
|
||||
val linkedHashMapConstructor: IrConstructorSymbol =
|
||||
javaUtilLinkedHashMap.owner.addConstructor().apply {
|
||||
addValueParameter("p_0", pluginContext.irBuiltIns.intType)
|
||||
}.symbol
|
||||
|
||||
val linkedHashMapPut: IrSimpleFunctionSymbol =
|
||||
javaUtilLinkedHashMap.owner.addFunction("put", pluginContext.irBuiltIns.anyNType).apply {
|
||||
addValueParameter("p_0", pluginContext.irBuiltIns.anyNType)
|
||||
addValueParameter("p_1", pluginContext.irBuiltIns.anyNType)
|
||||
}.symbol
|
||||
}
|
||||
|
||||
moduleFragment.transform(object: IrElementTransformerVoidWithContext() {
|
||||
override fun visitClassNew(declaration: IrClass): IrStatement {
|
||||
if (declaration.name.asString() == "A") {
|
||||
addFunWithExprBody(declaration)
|
||||
} else if (declaration.name.asString() == "B") {
|
||||
addFunWithUnsafeCoerce(declaration)
|
||||
} else if (declaration.name.asString() == "C") {
|
||||
addFunWithStubClass(declaration)
|
||||
} else if (declaration.name.asString() == "D") {
|
||||
addStaticFieldWithExprInit(declaration)
|
||||
} else if (declaration.name.asString() == "E") {
|
||||
addFunWithArrayListAdd(declaration)
|
||||
addFunWithLinkedHashMapPut(declaration)
|
||||
}
|
||||
|
||||
return super.visitClassNew(declaration)
|
||||
}
|
||||
|
||||
fun unsafeCoerce(value: IrExpression, fromType: IrType, toType: IrType): IrExpression {
|
||||
return IrCallImpl.fromSymbolOwner(-1, -1, toType, AndroidSymbols().unsafeCoerceIntrinsic).apply {
|
||||
putTypeArgument(0, fromType)
|
||||
putTypeArgument(1, toType)
|
||||
putValueArgument(0, value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun arrayListAdd(): IrExpression {
|
||||
// ArrayList(1).add(null)
|
||||
var androidSymbols = AndroidSymbols()
|
||||
return IrCallImpl.fromSymbolOwner(-1, -1, pluginContext.irBuiltIns.booleanType, androidSymbols.arrayListAdd).apply {
|
||||
dispatchReceiver = IrConstructorCallImpl.fromSymbolOwner(-1,-1, androidSymbols.javaUtilArrayList.typeWith(), androidSymbols.arrayListConstructor).apply {
|
||||
putValueArgument(0, IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1))
|
||||
}
|
||||
putValueArgument(0, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType))
|
||||
}
|
||||
}
|
||||
|
||||
private fun linkedHashMapPut(): IrExpression {
|
||||
// LinkedHashMap(1).put(null, null)
|
||||
var androidSymbols = AndroidSymbols()
|
||||
return IrCallImpl.fromSymbolOwner(-1, -1, pluginContext.irBuiltIns.anyNType, androidSymbols.linkedHashMapPut).apply {
|
||||
dispatchReceiver = IrConstructorCallImpl.fromSymbolOwner(-1,-1, androidSymbols.javaUtilLinkedHashMap.typeWith(), androidSymbols.linkedHashMapConstructor).apply {
|
||||
putValueArgument(0, IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1))
|
||||
}
|
||||
putValueArgument(0, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType))
|
||||
putValueArgument(1, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType))
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFunWithArrayListAdd(declaration: IrClass) {
|
||||
declaration.declarations.add(pluginContext.irFactory.buildFun {
|
||||
name = Name.identifier("<fn_ArrayListAdd>")
|
||||
returnType = pluginContext.irBuiltIns.booleanType
|
||||
}. also {
|
||||
it.body = DeclarationIrBuilder(pluginContext, it.symbol)
|
||||
.irExprBody(
|
||||
arrayListAdd()
|
||||
)
|
||||
it.parent = declaration
|
||||
})
|
||||
}
|
||||
|
||||
private fun addFunWithLinkedHashMapPut(declaration: IrClass) {
|
||||
declaration.declarations.add(pluginContext.irFactory.buildFun {
|
||||
name = Name.identifier("<fn_LinkedHashMap>")
|
||||
returnType = pluginContext.irBuiltIns.anyNType
|
||||
}. also {
|
||||
it.body = DeclarationIrBuilder(pluginContext, it.symbol)
|
||||
.irExprBody(
|
||||
linkedHashMapPut()
|
||||
)
|
||||
it.parent = declaration
|
||||
})
|
||||
}
|
||||
|
||||
private fun addFunWithUnsafeCoerce(declaration: IrClass) {
|
||||
val uintType = pluginContext.referenceClass(FqName("kotlin.UInt"))!!.owner.typeWith()
|
||||
declaration.declarations.add(pluginContext.irFactory.buildFun {
|
||||
name = Name.identifier("<fn>")
|
||||
returnType = uintType
|
||||
}. also {
|
||||
it.body = DeclarationIrBuilder(pluginContext, it.symbol)
|
||||
.irExprBody(
|
||||
unsafeCoerce(IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1), pluginContext.irBuiltIns.intType, uintType)
|
||||
)
|
||||
it.parent = declaration
|
||||
})
|
||||
}
|
||||
|
||||
private fun addFunWithExprBody(declaration: IrClass) {
|
||||
declaration.declarations.add(pluginContext.irFactory.buildFun {
|
||||
name = Name.identifier("<fn>")
|
||||
returnType = pluginContext.irBuiltIns.intType
|
||||
}. also {
|
||||
it.body = DeclarationIrBuilder(pluginContext, it.symbol)
|
||||
.irExprBody(
|
||||
IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 42)
|
||||
)
|
||||
it.parent = declaration
|
||||
})
|
||||
}
|
||||
|
||||
private fun addStaticFieldWithExprInit(declaration: IrClass) {
|
||||
declaration.declarations.add(pluginContext.irFactory.buildProperty {
|
||||
name = Name.identifier("bar")
|
||||
isConst = true
|
||||
visibility = DescriptorVisibilities.PRIVATE
|
||||
}.also { irProperty ->
|
||||
irProperty.backingField = pluginContext.irFactory.buildField {
|
||||
name = Name.identifier("bar")
|
||||
type = pluginContext.irBuiltIns.stringType
|
||||
isStatic = true
|
||||
visibility = DescriptorVisibilities.PRIVATE
|
||||
}.also { irField ->
|
||||
irField.initializer = DeclarationIrBuilder(pluginContext, irField.symbol)
|
||||
.irExprBody(
|
||||
IrConstImpl.string(-1, -1, pluginContext.irBuiltIns.stringType, "Foobar")
|
||||
)
|
||||
irField.parent = declaration
|
||||
}
|
||||
irProperty.parent = declaration
|
||||
})
|
||||
}
|
||||
|
||||
val javaLangPackage = IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(pluginContext.moduleDescriptor, FqName("java.lang"))
|
||||
|
||||
private fun makeJavaLangClass(fnName: String) = pluginContext.irFactory.buildClass {
|
||||
name = Name.identifier(fnName)
|
||||
kind = ClassKind.CLASS
|
||||
origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
}.apply {
|
||||
parent = javaLangPackage
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
}
|
||||
|
||||
// This adds a function with a parameter whose type is a real class without its supertypes specified,
|
||||
// mimicking the behaviour of the Kotlin android extensions gradle plugin, which refers to some real
|
||||
// Android classes through these sorts of synthetic, incomplete references. The extractor should
|
||||
// respond by replacing them with the real version available on the classpath.
|
||||
// I pick the particular java.lang class "ProcessBuilder" since it is (a) always available and
|
||||
// (b) not normally extracted by this project.
|
||||
private fun addFunWithStubClass(declaration: IrClass) {
|
||||
declaration.declarations.add(pluginContext.irFactory.buildFun {
|
||||
name = Name.identifier("<fn>")
|
||||
returnType = pluginContext.irBuiltIns.unitType
|
||||
}. also { addedFn ->
|
||||
val processBuilderStub = makeJavaLangClass("ProcessBuilder")
|
||||
val processBuilderStubType = processBuilderStub.defaultType
|
||||
val startProcessMethod = processBuilderStub.addFunction {
|
||||
name = Name.identifier("start")
|
||||
origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
modality = Modality.FINAL
|
||||
returnType = pluginContext.referenceClass(FqName("java.lang.Process"))!!.owner.defaultType
|
||||
}.apply {
|
||||
addDispatchReceiver { type = processBuilderStubType }
|
||||
}
|
||||
|
||||
val paramSymbol = addedFn.addValueParameter("param", processBuilderStubType)
|
||||
DeclarationIrBuilder(pluginContext, addedFn.symbol).apply {
|
||||
addedFn.body = irExprBody(irCall(startProcessMethod).apply { dispatchReceiver = irGet(paramSymbol) })
|
||||
addedFn.parent = declaration
|
||||
}
|
||||
})
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.github.codeql.TestComponentRegistrar
|
||||
@@ -0,0 +1,4 @@
|
||||
| file://:0:0:0:0 | fake.kotlin | FakeKotlinClass |
|
||||
| file://:0:0:0:0 | java.lang | Object |
|
||||
| file://:0:0:0:0 | kotlin | Any |
|
||||
| file://:0:0:0:0 | kotlin | TypeParam |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from ClassOrInterface ci
|
||||
where not exists(ci.getASupertype())
|
||||
select ci.getPackage(), ci.toString()
|
||||
@@ -0,0 +1 @@
|
||||
| d.kt:0:0:0:0 | bar | d.kt:0:0:0:0 | Foobar |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Field f, Expr init
|
||||
where init = f.getInitializer()
|
||||
select f, init
|
||||
@@ -0,0 +1,6 @@
|
||||
from create_database_utils import *
|
||||
import subprocess
|
||||
|
||||
subprocess.call("./build_plugin", shell=True)
|
||||
run_codeql_database_create(
|
||||
["kotlinc -J-Xmx2G -Xplugin=plugin.jar a.kt b.kt c.kt d.kt e.kt"], lang="java")
|
||||
2
java/ql/integration-tests/linux-only/kotlin/qlpack.yml
Normal file
2
java/ql/integration-tests/linux-only/kotlin/qlpack.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
libraryPathDependencies:
|
||||
- codeql-java
|
||||
@@ -0,0 +1,8 @@
|
||||
package extlib;
|
||||
|
||||
public class BoundedGenericTest<T extends CharSequence> {
|
||||
|
||||
public void method(T t) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package extlib;
|
||||
|
||||
public class ComplexBoundedGenericTest<A extends CharSequence, B extends A> {
|
||||
|
||||
public void method(A a, B b) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package extlib;
|
||||
|
||||
public class GenericTest<T> {
|
||||
|
||||
public void method(T t) { }
|
||||
|
||||
public void takesSelfMethod(GenericTest<T> selfLike) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package extlib;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Lib {
|
||||
|
||||
public void testParameterTypes(
|
||||
char p1,
|
||||
byte p2,
|
||||
short p3,
|
||||
int p4,
|
||||
long p5,
|
||||
float p6,
|
||||
double p7,
|
||||
boolean p8,
|
||||
Lib simpleClass,
|
||||
GenericTest<String> simpleGeneric,
|
||||
BoundedGenericTest<String> boundedGeneric,
|
||||
ComplexBoundedGenericTest<CharSequence, String> complexBoundedGeneric,
|
||||
int[] primitiveArray,
|
||||
Integer[] boxedTypeArray,
|
||||
int [][] multiDimensionalPrimitiveArray,
|
||||
Integer[][] multiDimensionalBoxedTypeArray,
|
||||
List<String>[] genericTypeArray,
|
||||
List<? extends CharSequence> producerWildcard,
|
||||
List<? super CharSequence> consumerWildcard,
|
||||
List<? extends List<? extends CharSequence>> nestedWildcard,
|
||||
List<?> unboundedWildcard) { }
|
||||
|
||||
public List<Integer> returnErasureTest() { return null; }
|
||||
|
||||
public <T> void paramErasureTest(List<String> param) { }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
parameterTypes
|
||||
| extlib.jar/extlib/GenericTest.class:0:0:0:0 | p0 | GenericTest<String> |
|
||||
| javasrc/extlib/GenericTest.java:7:31:7:53 | selfLike | GenericTest |
|
||||
| javasrc/extlib/Lib.java:8:5:8:11 | p1 | char |
|
||||
| javasrc/extlib/Lib.java:9:5:9:11 | p2 | byte |
|
||||
| javasrc/extlib/Lib.java:10:5:10:12 | p3 | short |
|
||||
| javasrc/extlib/Lib.java:11:5:11:10 | p4 | int |
|
||||
| javasrc/extlib/Lib.java:12:5:12:11 | p5 | long |
|
||||
| javasrc/extlib/Lib.java:13:5:13:12 | p6 | float |
|
||||
| javasrc/extlib/Lib.java:14:5:14:13 | p7 | double |
|
||||
| javasrc/extlib/Lib.java:15:5:15:14 | p8 | boolean |
|
||||
| javasrc/extlib/Lib.java:16:5:16:19 | simpleClass | Lib |
|
||||
| javasrc/extlib/Lib.java:17:5:17:37 | simpleGeneric | GenericTest<String> |
|
||||
| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest<String> |
|
||||
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> |
|
||||
| javasrc/extlib/Lib.java:20:5:20:24 | primitiveArray | int[] |
|
||||
| javasrc/extlib/Lib.java:21:5:21:28 | boxedTypeArray | Integer[] |
|
||||
| javasrc/extlib/Lib.java:22:5:22:43 | multiDimensionalPrimitiveArray | int[][] |
|
||||
| javasrc/extlib/Lib.java:23:5:23:46 | multiDimensionalBoxedTypeArray | Integer[][] |
|
||||
| javasrc/extlib/Lib.java:24:5:24:35 | genericTypeArray | List<String>[] |
|
||||
| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | List<? extends CharSequence> |
|
||||
| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | List<? super CharSequence> |
|
||||
| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | List<? extends List<? extends CharSequence>> |
|
||||
| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | List<?> |
|
||||
arrayTypes
|
||||
| javasrc/extlib/Lib.java:20:5:20:24 | primitiveArray | file://:0:0:0:0 | int[] | int | 1 | int |
|
||||
| javasrc/extlib/Lib.java:21:5:21:28 | boxedTypeArray | file://:0:0:0:0 | Integer[] | Integer | 1 | Integer |
|
||||
| javasrc/extlib/Lib.java:22:5:22:43 | multiDimensionalPrimitiveArray | file://:0:0:0:0 | int[][] | int | 2 | int[] |
|
||||
| javasrc/extlib/Lib.java:23:5:23:46 | multiDimensionalBoxedTypeArray | file://:0:0:0:0 | Integer[][] | Integer | 2 | Integer[] |
|
||||
| javasrc/extlib/Lib.java:24:5:24:35 | genericTypeArray | file://:0:0:0:0 | List<String>[] | List<String> | 1 | List<String> |
|
||||
wildcardTypes
|
||||
| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | file://:0:0:0:0 | ? extends CharSequence | upper | CharSequence |
|
||||
| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | file://:0:0:0:0 | ? super CharSequence | lower | CharSequence |
|
||||
| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | file://:0:0:0:0 | ? super CharSequence | upper | Object |
|
||||
| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | file://:0:0:0:0 | ? extends List<? extends CharSequence> | upper | List<? extends CharSequence> |
|
||||
| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | file://:0:0:0:0 | ? | upper | Object |
|
||||
parameterizedTypes
|
||||
| extlib.jar/extlib/GenericTest.class:0:0:0:0 | p0 | GenericTest<String> | String |
|
||||
| javasrc/extlib/GenericTest.java:7:31:7:53 | selfLike | GenericTest | T |
|
||||
| javasrc/extlib/Lib.java:17:5:17:37 | simpleGeneric | GenericTest<String> | String |
|
||||
| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest<String> | String |
|
||||
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> | CharSequence |
|
||||
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> | String |
|
||||
| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | List<? extends CharSequence> | ? extends CharSequence |
|
||||
| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | List<? super CharSequence> | ? super CharSequence |
|
||||
| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | List<? extends List<? extends CharSequence>> | ? extends List<? extends CharSequence> |
|
||||
| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | List<?> | ? |
|
||||
libCallables
|
||||
| javasrc/extlib/Lib.java:5:14:5:16 | Lib |
|
||||
| javasrc/extlib/Lib.java:7:15:7:32 | testParameterTypes |
|
||||
| javasrc/extlib/Lib.java:30:24:30:40 | returnErasureTest |
|
||||
| javasrc/extlib/Lib.java:32:19:32:34 | paramErasureTest |
|
||||
@@ -0,0 +1,40 @@
|
||||
import java
|
||||
|
||||
class ExtLibParameter extends Parameter {
|
||||
ExtLibParameter() { this.getCallable().getName() = ["testParameterTypes", "takesSelfMethod"] }
|
||||
}
|
||||
|
||||
query predicate parameterTypes(ExtLibParameter p, string t) { p.getType().toString() = t }
|
||||
|
||||
query predicate arrayTypes(
|
||||
ExtLibParameter p, Array at, string elementType, int dimension, string componentType
|
||||
) {
|
||||
p.getType() = at and
|
||||
at.getElementType().toString() = elementType and
|
||||
at.getDimension() = dimension and
|
||||
at.getComponentType().toString() = componentType
|
||||
}
|
||||
|
||||
query predicate wildcardTypes(ExtLibParameter p, Wildcard wc, string boundKind, string bound) {
|
||||
// Expose details of wildcard types:
|
||||
wc =
|
||||
[
|
||||
p.getType().(ParameterizedType).getATypeArgument(),
|
||||
p.getType().(ParameterizedType).getATypeArgument().(ParameterizedType).getATypeArgument()
|
||||
] and
|
||||
(
|
||||
boundKind = "upper" and bound = wc.getUpperBoundType().toString()
|
||||
or
|
||||
boundKind = "lower" and bound = wc.getLowerBoundType().toString()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate parameterizedTypes(ExtLibParameter p, string ptstr, string typeArg) {
|
||||
exists(ParameterizedType pt |
|
||||
p.getType() = pt and
|
||||
pt.getATypeArgument().toString() = typeArg and
|
||||
ptstr = pt.toString()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate libCallables(Callable c) { c.getFile().getBaseName().matches("%Lib.java") }
|
||||
@@ -0,0 +1,8 @@
|
||||
from create_database_utils import *
|
||||
import glob
|
||||
|
||||
os.mkdir('build')
|
||||
javaccmd = " ".join(["javac"] + glob.glob("javasrc/extlib/*.java") + ["-d", "build"])
|
||||
jarcmd = " ".join(["jar", "-c", "-f", "extlib.jar", "-C", "build", "extlib"])
|
||||
run_codeql_database_create([javaccmd, jarcmd, "kotlinc user.kt -cp extlib.jar"], lang="java")
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import extlib.*
|
||||
import java.util.*
|
||||
|
||||
fun test() {
|
||||
|
||||
// Pending better varargs support, avoiding listOf and mutableListOf
|
||||
val stringList = ArrayList<String>()
|
||||
val objectList = ArrayList<Any>()
|
||||
val stringStringList = ArrayList<ArrayList<String>>()
|
||||
|
||||
val lib = Lib()
|
||||
lib.testParameterTypes(
|
||||
'a',
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5.0f,
|
||||
6.0,
|
||||
true,
|
||||
Lib(),
|
||||
GenericTest<String>(),
|
||||
BoundedGenericTest<String>(),
|
||||
ComplexBoundedGenericTest<CharSequence, String>(),
|
||||
intArrayOf(1),
|
||||
arrayOf(1),
|
||||
arrayOf(intArrayOf(1)),
|
||||
arrayOf(arrayOf(1)),
|
||||
arrayOf(stringList),
|
||||
stringList,
|
||||
objectList,
|
||||
stringStringList,
|
||||
objectList)
|
||||
|
||||
val returnedList = lib.returnErasureTest()
|
||||
lib.paramErasureTest<Int>(listOf("Hello"))
|
||||
|
||||
// Check trap labelling consistency for methods that instantiate a generic type
|
||||
// with its own generic parameters -- for example, class MyList<T> { void addAll(MyList<T> l) { } },
|
||||
// which has the trap labelling oddity of looking like plain MyList, not MyList<T>, even though
|
||||
// this is a generic instantiation.
|
||||
val takesSelfTest = GenericTest<String>()
|
||||
takesSelfTest.takesSelfMethod(takesSelfTest)
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
class KotlinDefault {}
|
||||
@@ -0,0 +1 @@
|
||||
class KotlinDisabled {}
|
||||
@@ -0,0 +1 @@
|
||||
class KotlinEnabled {}
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
runSuccessfully(["kotlinc", "KotlinDefault.kt"])
|
||||
os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN'] = 'true'
|
||||
runSuccessfully(["kotlinc", "KotlinDisabled.kt"])
|
||||
del(os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN'])
|
||||
os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_ENABLE_KOTLIN'] = 'true'
|
||||
runSuccessfully(["kotlinc", "KotlinEnabled.kt"])
|
||||
@@ -0,0 +1 @@
|
||||
| KotlinEnabled.kt:1:1:1:22 | KotlinEnabled |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Class c
|
||||
where c.fromSource()
|
||||
select c
|
||||
@@ -0,0 +1,9 @@
|
||||
from create_database_utils import *
|
||||
|
||||
for var in ['CODEQL_EXTRACTOR_JAVA_AGENT_ENABLE_KOTLIN',
|
||||
'CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN']:
|
||||
if var in os.environ:
|
||||
del(os.environ[var])
|
||||
|
||||
run_codeql_database_create(['"%s" build.py' % sys.executable], lang="java")
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| code/A.kt:2:1:2:10 | A |
|
||||
| code/C.kt:2:1:2:10 | C |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Class c
|
||||
where c.fromSource()
|
||||
select c
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
class A {}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
class B {}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
class C {}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
os.environ['CODEQL_KOTLIN_INTERNAL_EXCEPTION_WHILE_EXTRACTING_FILE'] = 'B.kt'
|
||||
|
||||
subprocess.check_call(['kotlinc', 'A.kt', 'B.kt', 'C.kt', ])
|
||||
@@ -0,0 +1,3 @@
|
||||
| <compilation> | 0 | code/A.kt:0:0:0:0 | A | Extraction successful | Not recoverable errors | Not non-recoverable errors |
|
||||
| <compilation> | 1 | code/B.kt:0:0:0:0 | code/B.kt | Not extraction successful | Not recoverable errors | Non-recoverable errors |
|
||||
| <compilation> | 2 | code/C.kt:0:0:0:0 | C | Extraction successful | Not recoverable errors | Not non-recoverable errors |
|
||||
@@ -0,0 +1,24 @@
|
||||
import java
|
||||
|
||||
class AnonymousCompilation extends Compilation {
|
||||
override string toString() { result = "<compilation>" }
|
||||
}
|
||||
|
||||
from Compilation c, int i, File f
|
||||
where f = c.getFileCompiled(i)
|
||||
select c, i, f,
|
||||
any(string s |
|
||||
if c.fileCompiledSuccessful(i)
|
||||
then s = "Extraction successful"
|
||||
else s = "Not extraction successful"
|
||||
),
|
||||
any(string s |
|
||||
if c.fileCompiledRecoverableErrors(i)
|
||||
then s = "Recoverable errors"
|
||||
else s = "Not recoverable errors"
|
||||
),
|
||||
any(string s |
|
||||
if c.fileCompiledNonRecoverableErrors(i)
|
||||
then s = "Non-recoverable errors"
|
||||
else s = "Not non-recoverable errors"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
| <compilation> | Normal termination | Not extraction successful | Not recoverable errors | Non-recoverable errors |
|
||||
@@ -0,0 +1,24 @@
|
||||
import java
|
||||
|
||||
class AnonymousCompilation extends Compilation {
|
||||
override string toString() { result = "<compilation>" }
|
||||
}
|
||||
|
||||
from Compilation c
|
||||
select c,
|
||||
any(string s |
|
||||
if c.normalTermination() then s = "Normal termination" else s = "Not normal termination"
|
||||
),
|
||||
any(string s |
|
||||
if c.extractionSuccessful()
|
||||
then s = "Extraction successful"
|
||||
else s = "Not extraction successful"
|
||||
),
|
||||
any(string s |
|
||||
if c.recoverableErrors() then s = "Recoverable errors" else s = "Not recoverable errors"
|
||||
),
|
||||
any(string s |
|
||||
if c.nonRecoverableErrors()
|
||||
then s = "Non-recoverable errors"
|
||||
else s = "Not non-recoverable errors"
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(
|
||||
['"%s" build.py' % sys.executable],
|
||||
source="code", lang="java")
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This generated file contains a sample Kotlin application project to get you started.
|
||||
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
|
||||
* User Manual available at https://docs.gradle.org/7.0.2/userguide/building_java_projects.html
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.31'
|
||||
|
||||
// Apply the application plugin to add support for building a CLI application in Java.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Use Maven Central for resolving dependencies.
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'testProject.AppKt'
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This Kotlin source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package testProject
|
||||
|
||||
class App {
|
||||
val greeting: String
|
||||
get() {
|
||||
return "Hello World!"
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
// TODO: println(App().greeting)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
| 1 |
|
||||
@@ -0,0 +1,3 @@
|
||||
import java
|
||||
|
||||
select count(Compilation c)
|
||||
@@ -0,0 +1,2 @@
|
||||
| app/src/main/kotlin/testProject/App.kt:8:9:10:9 | getGreeting |
|
||||
| app/src/main/kotlin/testProject/App.kt:13:1:15:1 | main |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where exists(m.getFile().getRelativePath())
|
||||
select m
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/7.0.2/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'testProject'
|
||||
include('app')
|
||||
@@ -0,0 +1,4 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java")
|
||||
runSuccessfully(["gradle", "clean"])
|
||||
@@ -0,0 +1,432 @@
|
||||
app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| [CompilationUnit] App
|
||||
# 7| 1: [Class] Project
|
||||
# 0| 1: [Constructor] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] seen1
|
||||
# 0| 0: [TypeAccess] int
|
||||
# 0| 1: [Parameter] name
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [Parameter] language
|
||||
# 0| 0: [TypeAccess] int
|
||||
# 0| 3: [Parameter] serializationConstructorMarker
|
||||
# 0| 0: [TypeAccess] SerializationConstructorMarker
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [WhenExpr] when ...
|
||||
# 7| 0: [WhenBranch] ... -> ...
|
||||
# 7| 0: [ValueNEExpr] ... (value not-equals) ...
|
||||
# 7| 0: [IntegerLiteral] 3
|
||||
# 7| 1: [MethodAccess] and(...)
|
||||
# 7| -1: [IntegerLiteral] 3
|
||||
# 7| 0: [VarAccess] seen1
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] throwMissingFieldException(...)
|
||||
# 7| -1: [TypeAccess] PluginExceptionsKt
|
||||
# 7| 0: [VarAccess] seen1
|
||||
# 7| 1: [IntegerLiteral] 3
|
||||
# 7| 2: [MethodAccess] getDescriptor(...)
|
||||
# 7| -1: [VarAccess] INSTANCE
|
||||
# 7| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] Project.this.name
|
||||
# 7| -1: [ThisAccess] Project.this
|
||||
# 7| 0: [TypeAccess] Project
|
||||
# 7| 1: [VarAccess] name
|
||||
# 7| 3: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] Project.this.language
|
||||
# 7| -1: [ThisAccess] Project.this
|
||||
# 7| 0: [TypeAccess] Project
|
||||
# 7| 1: [VarAccess] language
|
||||
# 0| 1: [Method] write$Self
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] self
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 0| 1: [Parameter] output
|
||||
# 0| 0: [TypeAccess] CompositeEncoder
|
||||
# 0| 2: [Parameter] serialDesc
|
||||
# 0| 0: [TypeAccess] SerialDescriptor
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] encodeStringElement(...)
|
||||
# 7| -1: [VarAccess] output
|
||||
# 7| 0: [VarAccess] serialDesc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
# 7| 2: [MethodAccess] getName(...)
|
||||
# 7| -1: [VarAccess] self
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] encodeIntElement(...)
|
||||
# 7| -1: [VarAccess] output
|
||||
# 7| 0: [VarAccess] serialDesc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
# 7| 2: [MethodAccess] getLanguage(...)
|
||||
# 7| -1: [VarAccess] self
|
||||
# 0| 1: [Method] component1
|
||||
# 0| 3: [TypeAccess] String
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [VarAccess] this.name
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [Method] component2
|
||||
# 0| 3: [TypeAccess] int
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [Method] copy
|
||||
# 0| 3: [TypeAccess] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 8| 0: [Parameter] name
|
||||
# 8| 0: [TypeAccess] String
|
||||
# 8| 1: [Parameter] language
|
||||
# 8| 0: [TypeAccess] int
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [ClassInstanceExpr] new Project(...)
|
||||
# 0| -3: [TypeAccess] Project
|
||||
# 0| 0: [VarAccess] name
|
||||
# 0| 1: [VarAccess] language
|
||||
# 0| 1: [Method] toString
|
||||
# 0| 3: [TypeAccess] String
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [StringTemplateExpr] "..."
|
||||
# 0| 0: [StringLiteral] Project(
|
||||
# 0| 1: [StringLiteral] name=
|
||||
# 0| 2: [VarAccess] this.name
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 3: [StringLiteral] ,
|
||||
# 0| 4: [StringLiteral] language=
|
||||
# 0| 5: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 6: [StringLiteral] )
|
||||
# 0| 1: [Method] hashCode
|
||||
# 0| 3: [TypeAccess] int
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 0| 1: [LocalVariableDeclExpr] result
|
||||
# 0| 0: [MethodAccess] hashCode(...)
|
||||
# 0| -1: [VarAccess] this.name
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [ExprStmt] <Expr>;
|
||||
# 0| 0: [AssignExpr] ...=...
|
||||
# 0| 0: [VarAccess] result
|
||||
# 0| 1: [MethodAccess] plus(...)
|
||||
# 0| -1: [MethodAccess] times(...)
|
||||
# 0| -1: [VarAccess] result
|
||||
# 0| 0: [IntegerLiteral] 31
|
||||
# 0| 0: [MethodAccess] hashCode(...)
|
||||
# 0| -1: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 2: [ReturnStmt] return ...
|
||||
# 0| 0: [VarAccess] result
|
||||
# 0| 1: [Method] equals
|
||||
# 0| 3: [TypeAccess] boolean
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] other
|
||||
# 0| 0: [TypeAccess] Object
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ExprStmt] <Expr>;
|
||||
# 0| 0: [WhenExpr] when ...
|
||||
# 0| 0: [WhenBranch] ... -> ...
|
||||
# 0| 0: [EQExpr] ... == ...
|
||||
# 0| 0: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] other
|
||||
# 0| 1: [ReturnStmt] return ...
|
||||
# 0| 0: [BooleanLiteral] true
|
||||
# 0| 1: [ExprStmt] <Expr>;
|
||||
# 0| 0: [WhenExpr] when ...
|
||||
# 0| 0: [WhenBranch] ... -> ...
|
||||
# 0| 0: [NotInstanceOfExpr] ... !is ...
|
||||
# 0| 0: [VarAccess] other
|
||||
# 0| 1: [TypeAccess] Project
|
||||
# 0| 1: [ReturnStmt] return ...
|
||||
# 0| 0: [BooleanLiteral] false
|
||||
# 0| 2: [LocalVariableDeclStmt] var ...;
|
||||
# 0| 1: [LocalVariableDeclExpr] tmp0_other_with_cast
|
||||
# 0| 0: [CastExpr] (...)...
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 0| 1: [VarAccess] other
|
||||
# 0| 3: [ExprStmt] <Expr>;
|
||||
# 0| 0: [WhenExpr] when ...
|
||||
# 0| 0: [WhenBranch] ... -> ...
|
||||
# 0| 0: [ValueNEExpr] ... (value not-equals) ...
|
||||
# 0| 0: [VarAccess] this.name
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] tmp0_other_with_cast.name
|
||||
# 0| -1: [VarAccess] tmp0_other_with_cast
|
||||
# 0| 1: [ReturnStmt] return ...
|
||||
# 0| 0: [BooleanLiteral] false
|
||||
# 0| 4: [ExprStmt] <Expr>;
|
||||
# 0| 0: [WhenExpr] when ...
|
||||
# 0| 0: [WhenBranch] ... -> ...
|
||||
# 0| 0: [ValueNEExpr] ... (value not-equals) ...
|
||||
# 0| 0: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [VarAccess] tmp0_other_with_cast.language
|
||||
# 0| -1: [VarAccess] tmp0_other_with_cast
|
||||
# 0| 1: [ReturnStmt] return ...
|
||||
# 0| 0: [BooleanLiteral] false
|
||||
# 0| 5: [ReturnStmt] return ...
|
||||
# 0| 0: [BooleanLiteral] true
|
||||
# 7| 9: [Class] Companion
|
||||
# 0| 1: [Method] serializer
|
||||
# 0| 3: [TypeAccess] KSerializer<Project>
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [VarAccess] INSTANCE
|
||||
# 7| 2: [Constructor] Companion
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 9: [Class] $serializer
|
||||
# 0| 1: [Method] getDescriptor
|
||||
# 0| 3: [TypeAccess] SerialDescriptor
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [VarAccess] this.descriptor
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [FieldDeclaration] SerialDescriptor descriptor;
|
||||
# 0| -1: [TypeAccess] SerialDescriptor
|
||||
# 0| 1: [Method] childSerializers
|
||||
# 0| 3: [TypeAccess] KSerializer<?>[]
|
||||
# 0| 0: [TypeAccess] KSerializer<?>
|
||||
# 0| 0: [WildcardTypeAccess] ? ...
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [ArrayCreationExpr] new KSerializer<?>[]
|
||||
# 7| -2: [ArrayInit] {...}
|
||||
# 7| 0: [VarAccess] INSTANCE
|
||||
# 7| 1: [VarAccess] INSTANCE
|
||||
# 7| -1: [TypeAccess] KSerializer<?>
|
||||
# 7| 0: [IntegerLiteral] 2
|
||||
# 0| 1: [Method] deserialize
|
||||
# 0| 3: [TypeAccess] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] decoder
|
||||
# 0| 0: [TypeAccess] Decoder
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 7| 0: [MethodAccess] getDescriptor(...)
|
||||
# 7| -1: [ThisAccess] this
|
||||
# 7| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp1_flag
|
||||
# 7| 0: [BooleanLiteral] true
|
||||
# 7| 2: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp2_index
|
||||
# 7| 0: [IntegerLiteral] 0
|
||||
# 7| 3: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp3_bitMask0
|
||||
# 7| 0: [IntegerLiteral] 0
|
||||
# 7| 4: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp4_local0
|
||||
# 7| 0: [NullLiteral] null
|
||||
# 7| 5: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp5_local1
|
||||
# 7| 0: [IntegerLiteral] 0
|
||||
# 7| 6: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp6_input
|
||||
# 7| 0: [MethodAccess] beginStructure(...)
|
||||
# 7| -1: [VarAccess] decoder
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 7: [ExprStmt] <Expr>;
|
||||
# 7| 0: [WhenExpr] when ...
|
||||
# 7| 0: [WhenBranch] ... -> ...
|
||||
# 7| 0: [MethodAccess] decodeSequentially(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp4_local0
|
||||
# 7| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp3_bitMask0
|
||||
# 7| 1: [MethodAccess] or(...)
|
||||
# 7| -1: [VarAccess] tmp3_bitMask0
|
||||
# 7| 0: [IntegerLiteral] 1
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp5_local1
|
||||
# 7| 1: [MethodAccess] decodeIntElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp3_bitMask0
|
||||
# 7| 1: [MethodAccess] or(...)
|
||||
# 7| -1: [VarAccess] tmp3_bitMask0
|
||||
# 7| 0: [IntegerLiteral] 2
|
||||
# 7| 1: [WhenBranch] ... -> ...
|
||||
# 7| 0: [BooleanLiteral] true
|
||||
# 7| 1: [WhileStmt] while (...)
|
||||
# 7| 0: [VarAccess] tmp1_flag
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 1: [MethodAccess] decodeElementIndex(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [WhenExpr] when ...
|
||||
# 7| 0: [WhenBranch] ... -> ...
|
||||
# 7| 0: [ValueEQExpr] ... (value equals) ...
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 1: [IntegerLiteral] -1
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp1_flag
|
||||
# 7| 1: [BooleanLiteral] false
|
||||
# 7| 1: [WhenBranch] ... -> ...
|
||||
# 7| 0: [ValueEQExpr] ... (value equals) ...
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp4_local0
|
||||
# 7| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp3_bitMask0
|
||||
# 7| 1: [MethodAccess] or(...)
|
||||
# 7| -1: [VarAccess] tmp3_bitMask0
|
||||
# 7| 0: [IntegerLiteral] 1
|
||||
# 7| 2: [WhenBranch] ... -> ...
|
||||
# 7| 0: [ValueEQExpr] ... (value equals) ...
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp5_local1
|
||||
# 7| 1: [MethodAccess] decodeIntElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp3_bitMask0
|
||||
# 7| 1: [MethodAccess] or(...)
|
||||
# 7| -1: [VarAccess] tmp3_bitMask0
|
||||
# 7| 0: [IntegerLiteral] 2
|
||||
# 7| 3: [WhenBranch] ... -> ...
|
||||
# 7| 0: [BooleanLiteral] true
|
||||
# 7| 1: [ThrowStmt] throw ...
|
||||
# 7| 0: [ClassInstanceExpr] new UnknownFieldException(...)
|
||||
# 7| -3: [TypeAccess] UnknownFieldException
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 8: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] endStructure(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 9: [ReturnStmt] return ...
|
||||
# 7| 0: [ClassInstanceExpr] new Project(...)
|
||||
# 7| -3: [TypeAccess] Project
|
||||
# 7| 0: [VarAccess] tmp3_bitMask0
|
||||
# 7| 1: [VarAccess] tmp4_local0
|
||||
# 7| 2: [VarAccess] tmp5_local1
|
||||
# 7| 3: [NullLiteral] null
|
||||
# 0| 1: [Method] serialize
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] encoder
|
||||
# 0| 0: [TypeAccess] Encoder
|
||||
# 0| 1: [Parameter] value
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 7| 0: [MethodAccess] getDescriptor(...)
|
||||
# 7| -1: [ThisAccess] this
|
||||
# 7| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp1_output
|
||||
# 7| 0: [MethodAccess] beginStructure(...)
|
||||
# 7| -1: [VarAccess] encoder
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] write$Self(...)
|
||||
# 7| -1: [TypeAccess] Project
|
||||
# 7| 0: [VarAccess] value
|
||||
# 7| 1: [VarAccess] tmp1_output
|
||||
# 7| 2: [VarAccess] tmp0_desc
|
||||
# 7| 3: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] endStructure(...)
|
||||
# 7| -1: [VarAccess] tmp1_output
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 6: [Constructor] $serializer
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp0_serialDesc
|
||||
# 7| 0: [ClassInstanceExpr] new PluginGeneratedSerialDescriptor(...)
|
||||
# 7| -3: [TypeAccess] PluginGeneratedSerialDescriptor
|
||||
# 7| 0: [StringLiteral] testProject.Project
|
||||
# 7| 1: [ThisAccess] $serializer.this
|
||||
# 7| 0: [TypeAccess] $serializer
|
||||
# 7| 2: [IntegerLiteral] 2
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] addElement(...)
|
||||
# 7| -1: [VarAccess] tmp0_serialDesc
|
||||
# 7| 0: [StringLiteral] name
|
||||
# 7| 1: [BooleanLiteral] false
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] addElement(...)
|
||||
# 7| -1: [VarAccess] tmp0_serialDesc
|
||||
# 7| 0: [StringLiteral] language
|
||||
# 7| 1: [BooleanLiteral] false
|
||||
# 7| 3: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] $serializer.this.descriptor
|
||||
# 7| -1: [ThisAccess] $serializer.this
|
||||
# 7| 0: [TypeAccess] $serializer
|
||||
# 7| 1: [VarAccess] tmp0_serialDesc
|
||||
# 8| 11: [Constructor] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 8| 0: [Parameter] name
|
||||
# 8| 0: [TypeAccess] String
|
||||
# 8| 1: [Parameter] language
|
||||
# 8| 0: [TypeAccess] int
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 8| 1: [BlockStmt] { ... }
|
||||
# 8| 0: [ExprStmt] <Expr>;
|
||||
# 8| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 8| 0: [VarAccess] name
|
||||
# 8| 1: [ExprStmt] <Expr>;
|
||||
# 8| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 8| 0: [VarAccess] language
|
||||
# 8| 12: [Method] getName
|
||||
# 8| 3: [TypeAccess] String
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
# 8| 0: [ReturnStmt] return ...
|
||||
# 8| 0: [VarAccess] this.name
|
||||
# 8| -1: [ThisAccess] this
|
||||
# 8| 12: [FieldDeclaration] String name;
|
||||
# 8| -1: [TypeAccess] String
|
||||
# 8| 0: [VarAccess] name
|
||||
# 8| 14: [Method] getLanguage
|
||||
# 8| 3: [TypeAccess] int
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
# 8| 0: [ReturnStmt] return ...
|
||||
# 8| 0: [VarAccess] this.language
|
||||
# 8| -1: [ThisAccess] this
|
||||
# 8| 14: [FieldDeclaration] int language;
|
||||
# 8| -1: [TypeAccess] int
|
||||
# 8| 0: [VarAccess] language
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
@@ -0,0 +1,13 @@
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.6.10'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.10'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-serialization:1.6.10"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package testProject
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Project(val name: String, val language: Int)
|
||||
@@ -0,0 +1 @@
|
||||
| CodeQL Kotlin extractor | 2 | | Unbound object value, trying to use class stub from descriptor | app/src/main/kotlin/testProject/App.kt:7:1:8:55 | app/src/main/kotlin/testProject/App.kt:7:1:8:55 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from string genBy, int severity, string tag, string msg, Location l
|
||||
where diagnostics(_, genBy, severity, tag, msg, _, l)
|
||||
select genBy, severity, tag, msg, l
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/7.0.2/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'testProject'
|
||||
include('app')
|
||||
@@ -0,0 +1,4 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java")
|
||||
runSuccessfully(["gradle", "clean"])
|
||||
@@ -0,0 +1,24 @@
|
||||
| JavaSeesFirst/JarMtimesEqual/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___ClassFileMtimesEqual |
|
||||
| JavaSeesFirst/JarMtimesEqual/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___JavaClassFileNewer |
|
||||
| JavaSeesFirst/JarMtimesEqual/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___KotlinClassFileNewer |
|
||||
| JavaSeesFirst/JavaJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___ClassFileMtimesEqual |
|
||||
| JavaSeesFirst/JavaJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___JavaClassFileNewer |
|
||||
| JavaSeesFirst/JavaJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___KotlinClassFileNewer |
|
||||
| JavaSeesFirst/KotlinJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___ClassFileMtimesEqual |
|
||||
| JavaSeesFirst/KotlinJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___JavaClassFileNewer |
|
||||
| JavaSeesFirst/KotlinJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___KotlinClassFileNewer |
|
||||
| JavaSeesFirst/NoJar/ClassFileMtimesEqual/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___ClassFileMtimesEqual |
|
||||
| JavaSeesFirst/NoJar/JavaClassFileNewer/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___JavaClassFileNewer |
|
||||
| JavaSeesFirst/NoJar/KotlinClassFileNewer/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___KotlinClassFileNewer |
|
||||
| KotlinSeesFirst/JarMtimesEqual/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___ClassFileMtimesEqual |
|
||||
| KotlinSeesFirst/JarMtimesEqual/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___JavaClassFileNewer |
|
||||
| KotlinSeesFirst/JarMtimesEqual/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___KotlinClassFileNewer |
|
||||
| KotlinSeesFirst/JavaJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___ClassFileMtimesEqual |
|
||||
| KotlinSeesFirst/JavaJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___JavaClassFileNewer |
|
||||
| KotlinSeesFirst/JavaJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___KotlinClassFileNewer |
|
||||
| KotlinSeesFirst/KotlinJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___ClassFileMtimesEqual |
|
||||
| KotlinSeesFirst/KotlinJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___JavaClassFileNewer |
|
||||
| KotlinSeesFirst/KotlinJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___KotlinClassFileNewer |
|
||||
| KotlinSeesFirst/NoJar/ClassFileMtimesEqual/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___ClassFileMtimesEqual |
|
||||
| KotlinSeesFirst/NoJar/JavaClassFileNewer/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___JavaClassFileNewer |
|
||||
| KotlinSeesFirst/NoJar/KotlinClassFileNewer/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___KotlinClassFileNewer |
|
||||
@@ -0,0 +1,128 @@
|
||||
from create_database_utils import *
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
# Build a family of dependencies outside tracing, then refer to them from a traced build:
|
||||
|
||||
older_datetime = "202201010101"
|
||||
newer_datetime = "202202020202"
|
||||
|
||||
classpath_entries = dict()
|
||||
|
||||
extraction_orders = ["JavaSeesFirst", "KotlinSeesFirst"]
|
||||
jar_states = ["NoJar", "JarMtimesEqual", "JavaJarNewer", "KotlinJarNewer"]
|
||||
class_file_states = ["ClassFileMtimesEqual", "JavaClassFileNewer", "KotlinClassFileNewer"]
|
||||
|
||||
# Create test classes for each combination of which extractor will see the file first, the relative timestamps of the jar files seen by each, and the relative timestamps of the class file inside:
|
||||
|
||||
jobs = []
|
||||
|
||||
for first_extraction in extraction_orders:
|
||||
for jar_state in jar_states:
|
||||
for class_file_state in class_file_states:
|
||||
dep_dir = os.path.join(first_extraction, jar_state, class_file_state)
|
||||
dep_classname = "Dep___%s___%s___%s" % (first_extraction, jar_state, class_file_state)
|
||||
dep_seen_by_java_dir = os.path.join(dep_dir, "seen_by_java")
|
||||
dep_seen_by_kotlin_dir = os.path.join(dep_dir, "seen_by_kotlin")
|
||||
os.makedirs(dep_seen_by_java_dir)
|
||||
os.makedirs(dep_seen_by_kotlin_dir)
|
||||
dep_seen_by_java_sourcefile = os.path.join(dep_seen_by_java_dir, dep_classname + ".java")
|
||||
dep_seen_by_kotlin_sourcefile = os.path.join(dep_seen_by_kotlin_dir, dep_classname + ".java")
|
||||
with open(dep_seen_by_java_sourcefile, "w") as f:
|
||||
f.write("public class %s { }" % dep_classname)
|
||||
with open(dep_seen_by_kotlin_sourcefile, "w") as f:
|
||||
f.write("public class %s { void memberOnlySeenByKotlin() { } }" % dep_classname)
|
||||
jobs.append({
|
||||
"first_extraction": first_extraction,
|
||||
"jar_state": jar_state,
|
||||
"class_file_state": class_file_state,
|
||||
"dep_dir": dep_dir,
|
||||
"dep_classname": dep_classname,
|
||||
"dep_seen_by_java_dir": dep_seen_by_java_dir,
|
||||
"dep_seen_by_kotlin_dir": dep_seen_by_kotlin_dir,
|
||||
"dep_seen_by_java_sourcefile": dep_seen_by_java_sourcefile,
|
||||
"dep_seen_by_kotlin_sourcefile": dep_seen_by_kotlin_sourcefile
|
||||
})
|
||||
|
||||
# Compile all the test classes we just generated, in two commands (since javac objects to seeing the same class file twice in one run)
|
||||
|
||||
subprocess.check_call(["javac"] + [j["dep_seen_by_java_sourcefile"] for j in jobs])
|
||||
subprocess.check_call(["javac"] + [j["dep_seen_by_kotlin_sourcefile"] for j in jobs])
|
||||
|
||||
# Create jar files and set class and jar files' relative timestamps for each dependency the two extractors will see:
|
||||
|
||||
for j in jobs:
|
||||
os.remove(j["dep_seen_by_java_sourcefile"])
|
||||
os.remove(j["dep_seen_by_kotlin_sourcefile"])
|
||||
dep_seen_by_java_classfile = j["dep_seen_by_java_sourcefile"].replace(".java", ".class")
|
||||
dep_seen_by_kotlin_classfile = j["dep_seen_by_kotlin_sourcefile"].replace(".java", ".class")
|
||||
|
||||
subprocess.check_call(["touch", "-t", newer_datetime if j["class_file_state"] == "JavaClassFileNewer" else older_datetime, dep_seen_by_java_classfile])
|
||||
subprocess.check_call(["touch", "-t", newer_datetime if j["class_file_state"] == "KotlinClassFileNewer" else older_datetime, dep_seen_by_kotlin_classfile])
|
||||
|
||||
if j["jar_state"] != "NoJar":
|
||||
classfile_name = os.path.basename(dep_seen_by_java_classfile)
|
||||
jar_command = ["jar", "cf", "dep.jar", classfile_name]
|
||||
subprocess.check_call(jar_command, cwd = j["dep_seen_by_java_dir"])
|
||||
subprocess.check_call(jar_command, cwd = j["dep_seen_by_kotlin_dir"])
|
||||
jar_seen_by_java = os.path.join(j["dep_seen_by_java_dir"], "dep.jar")
|
||||
jar_seen_by_kotlin = os.path.join(j["dep_seen_by_kotlin_dir"], "dep.jar")
|
||||
subprocess.check_call(["touch", "-t", newer_datetime if j["jar_state"] == "JavaJarNewer" else older_datetime, jar_seen_by_java])
|
||||
subprocess.check_call(["touch", "-t", newer_datetime if j["jar_state"] == "KotlinJarNewer" else older_datetime, jar_seen_by_kotlin])
|
||||
j["javac_classpath_entry"] = jar_seen_by_java
|
||||
j["kotlinc_classpath_entry"] = jar_seen_by_kotlin
|
||||
else:
|
||||
# No jar file involved, just add the dependency build directory to the classpath:
|
||||
j["javac_classpath_entry"] = j["dep_seen_by_java_dir"]
|
||||
j["kotlinc_classpath_entry"] = j["dep_seen_by_kotlin_dir"]
|
||||
|
||||
# Create source files that instantiate each dependency type:
|
||||
|
||||
kotlin_first_jobs = [j for j in jobs if j["first_extraction"] == "KotlinSeesFirst"]
|
||||
java_first_jobs = [j for j in jobs if j["first_extraction"] == "JavaSeesFirst"]
|
||||
kotlin_first_classes = [j["dep_classname"] for j in kotlin_first_jobs]
|
||||
java_first_classes = [j["dep_classname"] for j in java_first_jobs]
|
||||
|
||||
kotlin_first_user = "kotlinFirstUser.kt"
|
||||
kotlin_second_user = "kotlinSecondUser.kt"
|
||||
java_first_user = "JavaFirstUser.java"
|
||||
java_second_user = "JavaSecondUser.java"
|
||||
|
||||
def kotlin_instantiate_classes(classes):
|
||||
return "; ".join(["noop(%s())" % c for c in classes])
|
||||
|
||||
def make_kotlin_user(user_filename, classes):
|
||||
with open(user_filename, "w") as f:
|
||||
f.write("fun noop(x: Any) { } fun user() { %s }" % kotlin_instantiate_classes(classes))
|
||||
|
||||
make_kotlin_user(kotlin_first_user, kotlin_first_classes)
|
||||
make_kotlin_user(kotlin_second_user, java_first_classes)
|
||||
|
||||
def java_instantiate_classes(classes):
|
||||
return " ".join(["noop(new %s());" % c for c in classes])
|
||||
|
||||
def make_java_user(user_filename, classes):
|
||||
with open(user_filename, "w") as f:
|
||||
f.write("public class %s { private static void noop(Object x) { } public static void user() { %s } }" % (user_filename.replace(".java", ""), java_instantiate_classes(classes)))
|
||||
|
||||
make_java_user(java_first_user, java_first_classes)
|
||||
make_java_user(java_second_user, kotlin_first_classes)
|
||||
|
||||
# Now finally make a database, including classes where Java sees them first followed by Kotlin and vice versa.
|
||||
# In all cases the Kotlin extraction should take precedence.
|
||||
|
||||
def make_classpath(jobs, entry_name):
|
||||
return ":".join([j[entry_name] for j in jobs])
|
||||
|
||||
kotlin_first_classpath = make_classpath(kotlin_first_jobs, "kotlinc_classpath_entry")
|
||||
java_first_classpath = make_classpath(java_first_jobs, "javac_classpath_entry")
|
||||
kotlin_second_classpath = make_classpath(java_first_jobs, "kotlinc_classpath_entry")
|
||||
java_second_classpath = make_classpath(kotlin_first_jobs, "javac_classpath_entry")
|
||||
|
||||
run_codeql_database_create([
|
||||
"kotlinc -cp %s %s" % (kotlin_first_classpath, kotlin_first_user),
|
||||
"javac -cp %s %s" % (java_first_classpath, java_first_user),
|
||||
"kotlinc -cp %s %s" % (kotlin_second_classpath, kotlin_second_user),
|
||||
"javac -cp %s %s" % (java_second_classpath, java_second_user)
|
||||
], lang="java")
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getName() = "memberOnlySeenByKotlin"
|
||||
select m, m.getDeclaringType().getName()
|
||||
@@ -0,0 +1 @@
|
||||
public class J<T> { }
|
||||
@@ -0,0 +1 @@
|
||||
fun user1(j: J<Int>) { }
|
||||
@@ -0,0 +1 @@
|
||||
fun user2(j: J<String>) { }
|
||||
@@ -0,0 +1,3 @@
|
||||
| J.java:1:14:1:14 | J |
|
||||
| build/J.class:0:0:0:0 | J<String> |
|
||||
| file:///!unknown-binary-location/J.class:0:0:0:0 | J<Integer> |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Class c
|
||||
where c.getSourceDeclaration().getName() = "J"
|
||||
select c
|
||||
@@ -0,0 +1,8 @@
|
||||
from create_database_utils import *
|
||||
|
||||
os.mkdir('build')
|
||||
# Steps:
|
||||
# 1. Compile Kotlin passing Java source code. J.class is extracted with an unknown binary location
|
||||
# 2. Compile Java producing a class file. J.class should be re-extracted this time with a known binary location
|
||||
# 3. Compile a Kotlin user passing a Java class file on the classpath. Should reference the class file location that step 1 didn't know, but step 2 did.
|
||||
run_codeql_database_create(["kotlinc J.java K.kt -d build", "javac J.java -d build", "kotlinc K2.kt -cp build -d build"], lang="java")
|
||||
@@ -0,0 +1,7 @@
|
||||
package abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij;
|
||||
|
||||
class Param {
|
||||
|
||||
}
|
||||
|
||||
fun f(p1: Param, p2: Param, p3: Param, p4: Param, p5: Param) { }
|
||||
@@ -0,0 +1 @@
|
||||
| <prefix>/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/LongsigKt.class:0:0:0:0 | f |
|
||||
@@ -0,0 +1,11 @@
|
||||
from create_database_utils import *
|
||||
import glob
|
||||
|
||||
# Compile library Kotlin file untraced. Note the library is hidden under `libsrc` so the Kotlin compiler
|
||||
# will certainly reference the jar, not the source or class file.
|
||||
|
||||
os.mkdir('build')
|
||||
runSuccessfully(["kotlinc"] + glob.glob("libsrc/*.kt") + ["-d", "build"])
|
||||
runSuccessfully(["jar", "cf", "extlib.jar", "-C", "build", "abcdefghij", "-C", "build", "META-INF"])
|
||||
run_codeql_database_create(["kotlinc user.kt -cp extlib.jar"], lang="java")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getDeclaringType().getName() = "LongsigKt"
|
||||
select m.getLocation()
|
||||
.toString()
|
||||
.regexpReplaceAll(".*(extlib.jar|!unknown-binary-location)/", "<prefix>/"), m.toString()
|
||||
@@ -0,0 +1,7 @@
|
||||
import abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.*
|
||||
|
||||
fun user() {
|
||||
|
||||
f(Param(), Param(), Param(), Param(), Param())
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
public class JavaDefns {
|
||||
|
||||
// Currently known not to work: the Comparable<? extends X> case, which Kotlin sees as Comparable<*> because the
|
||||
// wildcard goes the opposite direction to the variance declared on Comparable's type parameter.
|
||||
|
||||
public static void takesComparable(Comparable<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
|
||||
|
||||
public static void takesNestedComparable(Comparable<Comparable<? super CharSequence>> innerContravar, Comparable<? super Comparable<CharSequence>> outerContravar) { }
|
||||
|
||||
public static void takesArrayOfComparable(Comparable<CharSequence>[] invar, Comparable<? super CharSequence>[] contravar) { }
|
||||
|
||||
public static Comparable<? super CharSequence> returnsWildcard() { return null; }
|
||||
|
||||
public static Comparable<CharSequence> returnsInvariant() { return null; }
|
||||
|
||||
public JavaDefns(Comparable<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import java.util.List;
|
||||
|
||||
public class JavaUser {
|
||||
|
||||
public static void test() {
|
||||
|
||||
KotlinDefns kd = new KotlinDefns();
|
||||
|
||||
kd.takesInvariantType((List<CharSequence>)null, (List<? extends CharSequence>)null, (List<? super CharSequence>)null);
|
||||
|
||||
kd.takesCovariantType((List<? extends CharSequence>)null, (List<? extends CharSequence>)null);
|
||||
|
||||
kd.takesContravariantType((Comparable<? super CharSequence>)null, (Comparable<? super CharSequence>)null);
|
||||
|
||||
kd.takesNestedType((List<List<CharSequence>>) null, (List<? extends List<? extends CharSequence>>)null, (Comparable<? super Comparable<? super CharSequence>>)null, (List<? extends Comparable<? super CharSequence>>)null, (Comparable<? super List<? extends CharSequence>>)null);
|
||||
|
||||
kd.takesFinalParameter((List<String>)null, (List<String>)null, (Comparable<? super String>)null);
|
||||
|
||||
kd.takesFinalParameterForceWildcard((List<String>)null, (List<? extends String>)null, (Comparable<? super String>)null);
|
||||
|
||||
kd.takesAnyParameter((List<Object>)null, (List<? extends Object>)null, (Comparable<Object>)null);
|
||||
|
||||
kd.takesAnyQParameter((List<Object>)null, (List<? extends Object>)null, (Comparable<Object>)null);
|
||||
|
||||
kd.takesAnyParameterForceWildcard((List<Object>)null, (List<? extends Object>)null, (Comparable<? super Object>)null);
|
||||
|
||||
kd.takesVariantTypesSuppressedWildcards((List<CharSequence>)null, (Comparable<CharSequence>)null);
|
||||
|
||||
List<CharSequence> r1 = kd.returnsInvar();
|
||||
|
||||
List<CharSequence> r2 = kd.returnsCovar();
|
||||
|
||||
Comparable<CharSequence> r3 = kd.returnsContravar();
|
||||
|
||||
List<? extends CharSequence> r4 = kd.returnsCovarForced();
|
||||
|
||||
Comparable<? super CharSequence> r5 = kd.returnsContravarForced();
|
||||
|
||||
KotlinDefnsSuppressedOuter kdso = new KotlinDefnsSuppressedOuter();
|
||||
kdso.outerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
|
||||
KotlinDefnsSuppressedOuter.Inner kdsoi = new KotlinDefnsSuppressedOuter.Inner();
|
||||
kdsoi.innerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
|
||||
|
||||
KotlinDefnsSuppressedInner kdsi = new KotlinDefnsSuppressedInner();
|
||||
kdsi.outerFn((List<? extends CharSequence>)null, (Comparable<? super CharSequence>)null);
|
||||
KotlinDefnsSuppressedInner.Inner kdsii = new KotlinDefnsSuppressedInner.Inner();
|
||||
kdsii.innerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
|
||||
|
||||
KotlinDefnsSuppressedFn kdsf = new KotlinDefnsSuppressedFn();
|
||||
kdsf.outerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Note throughout, using:
|
||||
// MutableList as a type whose parameter is invariant
|
||||
// List as a type whose parameter is covariant (List<out T>)
|
||||
// Comparable as a type whose parameter is contravariant (Comparable<int T>)
|
||||
// CharSequence as a non-final type
|
||||
// String as a final type
|
||||
|
||||
class ComparableCs : Comparable<CharSequence> {
|
||||
override fun compareTo(other: CharSequence): Int = 1
|
||||
}
|
||||
|
||||
class KotlinDefns {
|
||||
|
||||
fun takesInvariantType(noUseSiteVariance: MutableList<CharSequence>, useSiteCovariant: MutableList<out CharSequence>, useSiteContravariant: MutableList<in CharSequence>) { }
|
||||
|
||||
// Note List<in CharSequence> is a static error (contradictory variance)
|
||||
fun takesCovariantType(noUseSiteVariance: List<CharSequence>, useSiteCovariant: List<out CharSequence>) { }
|
||||
|
||||
// Note Comparable<out CharSequence> is a static error (contradictory variance)
|
||||
fun takesContravariantType(noUseSiteVariance: Comparable<CharSequence>, useSiteContravariant: Comparable<in CharSequence>) { }
|
||||
|
||||
fun takesNestedType(invar: MutableList<MutableList<CharSequence>>, covar: List<List<CharSequence>>, contravar: Comparable<Comparable<CharSequence>>, mixed1: List<Comparable<CharSequence>>, mixed2: Comparable<List<CharSequence>>) { }
|
||||
|
||||
fun takesFinalParameter(invar: MutableList<String>, covar: List<String>, contravar: Comparable<String>) { }
|
||||
|
||||
fun takesFinalParameterForceWildcard(invar: MutableList<@JvmWildcard String>, covar: List<@JvmWildcard String>, contravar: Comparable<@JvmWildcard String>) { }
|
||||
|
||||
fun takesAnyParameter(invar: MutableList<Any>, covar: List<Any>, contravar: Comparable<Any>) { }
|
||||
|
||||
fun takesAnyQParameter(invar: MutableList<Any?>, covar: List<Any?>, contravar: Comparable<Any?>) { }
|
||||
|
||||
fun takesAnyParameterForceWildcard(invar: MutableList<@JvmWildcard Any>, covar: List<@JvmWildcard Any>, contravar: Comparable<@JvmWildcard Any>) { }
|
||||
|
||||
fun takesVariantTypesSuppressedWildcards(covar: List<@JvmSuppressWildcards CharSequence>, contravar: Comparable<@JvmSuppressWildcards CharSequence>) { }
|
||||
|
||||
fun returnsInvar() : MutableList<CharSequence> = mutableListOf()
|
||||
|
||||
fun returnsCovar(): List<CharSequence> = listOf()
|
||||
|
||||
fun returnsContravar(): Comparable<CharSequence> = ComparableCs()
|
||||
|
||||
fun returnsCovarForced(): List<@JvmWildcard CharSequence> = listOf()
|
||||
|
||||
fun returnsContravarForced(): Comparable<@JvmWildcard CharSequence> = ComparableCs()
|
||||
|
||||
}
|
||||
|
||||
@JvmSuppressWildcards
|
||||
class KotlinDefnsSuppressedOuter {
|
||||
|
||||
fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
|
||||
|
||||
class Inner {
|
||||
|
||||
fun innerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class KotlinDefnsSuppressedInner {
|
||||
|
||||
fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
|
||||
|
||||
@JvmSuppressWildcards
|
||||
class Inner {
|
||||
|
||||
fun innerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class KotlinDefnsSuppressedFn {
|
||||
|
||||
@JvmSuppressWildcards fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
fun user() {
|
||||
val cs = ComparableCs()
|
||||
val acs = arrayOf(cs)
|
||||
|
||||
JavaDefns.takesComparable(cs, cs)
|
||||
JavaDefns.takesArrayOfComparable(acs, acs)
|
||||
|
||||
val constructed = JavaDefns(cs, cs)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
| JavaDefns | JavaDefns | contravar | Comparable<? super CharSequence> |
|
||||
| JavaDefns | JavaDefns | invar | Comparable<CharSequence> |
|
||||
| JavaDefns | returnsInvariant | return | Comparable<CharSequence> |
|
||||
| JavaDefns | returnsWildcard | return | Comparable<? super CharSequence> |
|
||||
| JavaDefns | takesArrayOfComparable | contravar | Comparable<? super CharSequence>[] |
|
||||
| JavaDefns | takesArrayOfComparable | invar | Comparable<CharSequence>[] |
|
||||
| JavaDefns | takesComparable | contravar | Comparable<? super CharSequence> |
|
||||
| JavaDefns | takesComparable | invar | Comparable<CharSequence> |
|
||||
| JavaDefns | takesNestedComparable | innerContravar | Comparable<Comparable<? super CharSequence>> |
|
||||
| JavaDefns | takesNestedComparable | outerContravar | Comparable<? super Comparable<CharSequence>> |
|
||||
| KotlinDefns | returnsContravar | return | Comparable<CharSequence> |
|
||||
| KotlinDefns | returnsContravarForced | return | Comparable<? super CharSequence> |
|
||||
| KotlinDefns | returnsCovar | return | List<CharSequence> |
|
||||
| KotlinDefns | returnsCovarForced | return | List<? extends CharSequence> |
|
||||
| KotlinDefns | returnsInvar | return | List<CharSequence> |
|
||||
| KotlinDefns | takesAnyParameter | contravar | Comparable<Object> |
|
||||
| KotlinDefns | takesAnyParameter | covar | List<? extends Object> |
|
||||
| KotlinDefns | takesAnyParameter | invar | List<Object> |
|
||||
| KotlinDefns | takesAnyParameterForceWildcard | contravar | Comparable<? super Object> |
|
||||
| KotlinDefns | takesAnyParameterForceWildcard | covar | List<? extends Object> |
|
||||
| KotlinDefns | takesAnyParameterForceWildcard | invar | List<Object> |
|
||||
| KotlinDefns | takesAnyQParameter | contravar | Comparable<Object> |
|
||||
| KotlinDefns | takesAnyQParameter | covar | List<? extends Object> |
|
||||
| KotlinDefns | takesAnyQParameter | invar | List<Object> |
|
||||
| KotlinDefns | takesContravariantType | noUseSiteVariance | Comparable<? super CharSequence> |
|
||||
| KotlinDefns | takesContravariantType | useSiteContravariant | Comparable<? super CharSequence> |
|
||||
| KotlinDefns | takesCovariantType | noUseSiteVariance | List<? extends CharSequence> |
|
||||
| KotlinDefns | takesCovariantType | useSiteCovariant | List<? extends CharSequence> |
|
||||
| KotlinDefns | takesFinalParameter | contravar | Comparable<? super String> |
|
||||
| KotlinDefns | takesFinalParameter | covar | List<String> |
|
||||
| KotlinDefns | takesFinalParameter | invar | List<String> |
|
||||
| KotlinDefns | takesFinalParameterForceWildcard | contravar | Comparable<? super String> |
|
||||
| KotlinDefns | takesFinalParameterForceWildcard | covar | List<? extends String> |
|
||||
| KotlinDefns | takesFinalParameterForceWildcard | invar | List<String> |
|
||||
| KotlinDefns | takesInvariantType | noUseSiteVariance | List<CharSequence> |
|
||||
| KotlinDefns | takesInvariantType | useSiteContravariant | List<? super CharSequence> |
|
||||
| KotlinDefns | takesInvariantType | useSiteCovariant | List<? extends CharSequence> |
|
||||
| KotlinDefns | takesNestedType | contravar | Comparable<? super Comparable<? super CharSequence>> |
|
||||
| KotlinDefns | takesNestedType | covar | List<? extends List<? extends CharSequence>> |
|
||||
| KotlinDefns | takesNestedType | invar | List<List<CharSequence>> |
|
||||
| KotlinDefns | takesNestedType | mixed1 | List<? extends Comparable<? super CharSequence>> |
|
||||
| KotlinDefns | takesNestedType | mixed2 | Comparable<? super List<? extends CharSequence>> |
|
||||
| KotlinDefns | takesVariantTypesSuppressedWildcards | contravar | Comparable<CharSequence> |
|
||||
| KotlinDefns | takesVariantTypesSuppressedWildcards | covar | List<CharSequence> |
|
||||
| KotlinDefnsSuppressedFn | outerFn | contravar | Comparable<CharSequence> |
|
||||
| KotlinDefnsSuppressedFn | outerFn | covar | List<CharSequence> |
|
||||
| KotlinDefnsSuppressedInner | outerFn | contravar | Comparable<? super CharSequence> |
|
||||
| KotlinDefnsSuppressedInner | outerFn | covar | List<? extends CharSequence> |
|
||||
| KotlinDefnsSuppressedInner$Inner | innerFn | contravar | Comparable<CharSequence> |
|
||||
| KotlinDefnsSuppressedInner$Inner | innerFn | covar | List<CharSequence> |
|
||||
| KotlinDefnsSuppressedOuter | outerFn | contravar | Comparable<CharSequence> |
|
||||
| KotlinDefnsSuppressedOuter | outerFn | covar | List<CharSequence> |
|
||||
| KotlinDefnsSuppressedOuter$Inner | innerFn | contravar | Comparable<CharSequence> |
|
||||
| KotlinDefnsSuppressedOuter$Inner | innerFn | covar | List<CharSequence> |
|
||||
@@ -0,0 +1,3 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create(["kotlinc kotlindefns.kt", "javac JavaUser.java JavaDefns.java -cp .", "kotlinc -cp . kotlinuser.kt"], lang="java")
|
||||
@@ -0,0 +1,22 @@
|
||||
import java
|
||||
|
||||
predicate isInterestingClass(Class c) {
|
||||
[c, c.(NestedType).getEnclosingType()].getName().matches(["KotlinDefns%", "JavaDefns"])
|
||||
}
|
||||
|
||||
from Callable c, string paramOrReturnName, Type paramOrReturnType
|
||||
where
|
||||
isInterestingClass(c.getDeclaringType()) and
|
||||
(
|
||||
exists(Parameter p |
|
||||
p = c.getAParameter() and
|
||||
paramOrReturnName = p.getName() and
|
||||
paramOrReturnType = p.getType()
|
||||
)
|
||||
or
|
||||
paramOrReturnName = "return" and
|
||||
paramOrReturnType = c.getReturnType() and
|
||||
not paramOrReturnType instanceof VoidType
|
||||
)
|
||||
select c.getDeclaringType().getQualifiedName(), c.getName(), paramOrReturnName,
|
||||
paramOrReturnType.toString()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user