Merge pull request #9122 from smowton/smowton/admin/update-kotlin

Kotlin: Apply changes since https://github.com/github/codeql/pull/9109 branched away from kotlin-main
This commit is contained in:
Chris Smowton
2022-05-13 12:00:03 +01:00
committed by GitHub
50 changed files with 552 additions and 179 deletions

View File

@@ -93,9 +93,9 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
ftw.writeCupackage(ftw.fileId, pkgId)
fileExtractor.extractClassSource(irDecl, !irDecl.isFileClass, false)
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
} else {
fileExtractor.extractDeclaration(irDecl)
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
}
}

View File

@@ -74,7 +74,7 @@ open class KotlinFileExtractor(
}
}
file.declarations.map { extractDeclaration(it) }
file.declarations.map { extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) }
extractStaticInitializer(file, null)
CommentExtractor(this, file, tw.fileId).extract()
}
@@ -91,20 +91,29 @@ open class KotlinFileExtractor(
return false
}
fun extractDeclaration(declaration: IrDeclaration) {
private fun shouldExtractDecl(declaration: IrDeclaration, extractPrivateMembers: Boolean) =
extractPrivateMembers ||
when(declaration) {
is IrDeclarationWithVisibility -> declaration.visibility.let { it != DescriptorVisibilities.PRIVATE && it != DescriptorVisibilities.PRIVATE_TO_THIS }
else -> true
}
fun extractDeclaration(declaration: IrDeclaration, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) {
with("declaration", declaration) {
if (!shouldExtractDecl(declaration, extractPrivateMembers))
return
when (declaration) {
is IrClass -> {
if (isExternalDeclaration(declaration)) {
extractExternalClassLater(declaration)
} else {
extractClassSource(declaration, extractDeclarations = true, extractStaticInitializer = true)
extractClassSource(declaration, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies)
}
}
is IrFunction -> {
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
if (parentId != null) {
extractFunction(declaration, parentId, true, null, listOf())
extractFunction(declaration, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, null, listOf())
}
Unit
}
@@ -114,14 +123,14 @@ open class KotlinFileExtractor(
is IrProperty -> {
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
if (parentId != null) {
extractProperty(declaration, parentId, true, null, listOf())
extractProperty(declaration, parentId, extractBackingField = true, extractFunctionBodies = extractFunctionBodies, null, listOf())
}
Unit
}
is IrEnumEntry -> {
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
if (parentId != null) {
extractEnumEntry(declaration, parentId)
extractEnumEntry(declaration, parentId, extractFunctionBodies)
}
Unit
}
@@ -320,7 +329,7 @@ open class KotlinFileExtractor(
// `argsIncludingOuterClasses` can be null to describe a raw generic type.
// For non-generic types it will be zero-length list.
fun extractMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, id: Label<out DbClassorinterface>) {
fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, id: Label<out DbClassorinterface>) {
with("member prototypes", c) {
val typeParamSubstitution =
when (argsIncludingOuterClasses) {
@@ -339,17 +348,19 @@ open class KotlinFileExtractor(
}
c.declarations.map {
when(it) {
is IrFunction -> extractFunction(it, id, false, typeParamSubstitution, argsIncludingOuterClasses)
is IrProperty -> extractProperty(it, id, false, typeParamSubstitution, argsIncludingOuterClasses)
else -> {}
if (shouldExtractDecl(it, false)) {
when(it) {
is IrFunction -> extractFunction(it, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, typeParamSubstitution, argsIncludingOuterClasses)
is IrProperty -> extractProperty(it, id, extractBackingField = false, extractFunctionBodies = false, typeParamSubstitution, argsIncludingOuterClasses)
else -> {}
}
}
}
}
}
private fun extractLocalTypeDeclStmt(c: IrClass, callable: Label<out DbCallable>, parent: Label<out DbStmtparent>, idx: Int) {
val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true).cast<DbClass>()
val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true).cast<DbClass>()
extractLocalTypeDeclStmt(id, c, callable, parent, idx)
}
@@ -361,7 +372,7 @@ open class KotlinFileExtractor(
tw.writeHasLocation(stmtId, locId)
}
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean): Label<out DbClassorinterface> {
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
with("class source", c) {
DeclarationStackAdjuster(c).use {
@@ -395,7 +406,7 @@ open class KotlinFileExtractor(
c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx) }
if (extractDeclarations) {
c.declarations.map { extractDeclaration(it) }
c.declarations.map { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) }
if (extractStaticInitializer)
extractStaticInitializer(c, id)
}
@@ -442,7 +453,7 @@ open class KotlinFileExtractor(
val instance = useCompanionObjectClassInstance(innerDeclaration)
if (instance != null) {
val type = useSimpleTypeClass(innerDeclaration, emptyList(), false)
tw.writeFields(instance.id, instance.name, type.javaResult.id, innerId, instance.id)
tw.writeFields(instance.id, instance.name, type.javaResult.id, parentId, instance.id)
tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id)
tw.writeHasLocation(instance.id, innerLocId)
addModifiers(instance.id, "public", "static", "final")
@@ -500,11 +511,11 @@ open class KotlinFileExtractor(
return FieldResult(instanceId, instanceName)
}
private fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label<out DbCallable>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): TypeResults {
private fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label<out DbCallable>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, extractTypeAccess: Boolean): TypeResults {
with("value parameter", vp) {
val location = getLocation(vp, classTypeArgsIncludingOuterClasses)
val id = useValueParameter(vp, parent)
if (!isExternalDeclaration(vp)) {
if (extractTypeAccess) {
extractTypeAccessRecursive(vp.type, location, id, -1)
}
return extractValueParameter(id, vp.type, vp.name.asString(), location, parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
@@ -539,7 +550,7 @@ open class KotlinFileExtractor(
classTypeArgsIncludingOuterClasses = listOf()
)
val clinitId = tw.getLabelFor<DbMethod>(clinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, parentId, clinitId)
tw.writeMethodsKotlinType(clinitId, returnType.kotlinResult.id)
@@ -665,7 +676,7 @@ open class KotlinFileExtractor(
}
}
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null): Label<out DbCallable>? {
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null): Label<out DbCallable>? {
if (isFake(f)) return null
with("function", f) {
@@ -678,7 +689,9 @@ open class KotlinFileExtractor(
?: if (f.isLocalFunction())
getLocallyVisibleFunctionLabels(f).function
else
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses)
// 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)
@@ -689,13 +702,13 @@ open class KotlinFileExtractor(
val extReceiver = f.extensionReceiverParameter
val idxOffset = if (extReceiver != null) 1 else 0
val paramTypes = f.valueParameters.mapIndexed { i, vp ->
extractValueParameter(vp, id, i + idxOffset, typeSubstitution, sourceDeclaration, classTypeArgsIncludingOuterClasses)
extractValueParameter(vp, id, i + idxOffset, typeSubstitution, sourceDeclaration, classTypeArgsIncludingOuterClasses, extractTypeAccess = extractMethodAndParameterTypeAccesses)
}
val allParamTypes = if (extReceiver != null) {
val extendedType = useType(extReceiver.type)
tw.writeKtExtensionFunctions(id.cast<DbMethod>(), extendedType.javaResult.id, extendedType.kotlinResult.id)
val t = extractValueParameter(extReceiver, id, 0, null, sourceDeclaration, classTypeArgsIncludingOuterClasses)
val t = extractValueParameter(extReceiver, id, 0, null, sourceDeclaration, classTypeArgsIncludingOuterClasses, extractTypeAccess = extractMethodAndParameterTypeAccesses)
listOf(t) + paramTypes
} else {
paramTypes
@@ -724,7 +737,7 @@ open class KotlinFileExtractor(
tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast<DbMethod>())
tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id)
if (!isExternalDeclaration(f)) {
if (extractMethodAndParameterTypeAccesses) {
extractTypeAccessRecursive(f.returnType, locId, id, -1)
}
@@ -791,14 +804,14 @@ open class KotlinFileExtractor(
return id
}
fun extractProperty(p: IrProperty, parentId: Label<out DbReftype>, extractBackingField: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgs: List<IrTypeArgument>?) {
fun extractProperty(p: IrProperty, parentId: Label<out DbReftype>, extractBackingField: Boolean, extractFunctionBodies: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) {
with("property", p) {
if (isFake(p)) return
DeclarationStackAdjuster(p).use {
val id = useProperty(p, parentId)
val locId = getLocation(p, classTypeArgs)
val id = useProperty(p, parentId, classTypeArgsIncludingOuterClasses)
val locId = getLocation(p, classTypeArgsIncludingOuterClasses)
tw.writeKtProperties(id, p.name.asString())
tw.writeHasLocation(id, locId)
@@ -807,7 +820,7 @@ open class KotlinFileExtractor(
val setter = p.setter
if (getter != null) {
val getterId = extractFunction(getter, parentId, extractBackingField, typeSubstitution, classTypeArgs)?.cast<DbMethod>()
val getterId = extractFunction(getter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast<DbMethod>()
if (getterId != null) {
tw.writeKtPropertyGetters(id, getterId)
}
@@ -821,7 +834,7 @@ open class KotlinFileExtractor(
if (!p.isVar) {
logger.errorElement("!isVar property with a setter", p)
}
val setterId = extractFunction(setter, parentId, extractBackingField, typeSubstitution, classTypeArgs)?.cast<DbMethod>()
val setterId = extractFunction(setter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast<DbMethod>()
if (setterId != null) {
tw.writeKtPropertySetters(id, setterId)
}
@@ -857,7 +870,7 @@ open class KotlinFileExtractor(
}
}
fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>) {
fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>, extractTypeAccess: Boolean) {
with("enum entry", ee) {
DeclarationStackAdjuster(ee).use {
val id = useEnumEntry(ee)
@@ -867,7 +880,7 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(ee)
tw.writeHasLocation(id, locId)
if (!isExternalDeclaration(ee)) {
if (extractTypeAccess) {
val fieldDeclarationId = tw.getFreshIdLabel<DbFielddecl>()
tw.writeFielddecls(fieldDeclarationId, parentId)
tw.writeFieldDeclaredIn(id, fieldDeclarationId, 0)
@@ -1341,6 +1354,23 @@ open class KotlinFileExtractor(
return result
}
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? {
val fn = pluginContext.referenceFunctions(FqName(functionFilter))
.firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type }
?.owner
if (fn != null) {
if (fn.parentClassOrNull != null) {
extractExternalClassLater(fn.parentAsClass)
}
} else {
logger.errorElement("Couldn't find JVM intrinsic function $functionFilter in $type", warnAgainstElement)
}
return fn
}
val javaLangString by lazy {
val result = pluginContext.referenceClass(FqName("java.lang.String"))?.owner
result?.let { extractExternalClassLater(it) }
@@ -1854,6 +1884,11 @@ open class KotlinFileExtractor(
}
}
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> {
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn ->
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, listOf((c.dispatchReceiver!!.type as IrSimpleType).arguments.first().typeOrNull!!))
}
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "get") && c.origin == IrStatementOrigin.GET_ARRAY_ELEMENT -> {
val id = tw.getFreshIdLabel<DbArrayaccess>()
val type = useType(c.type)
@@ -3976,7 +4011,7 @@ open class KotlinFileExtractor(
helper.extractParameterToFieldAssignmentInConstructor("<fn>", functionType, fieldId, 0, 1)
// add implementation function
extractFunction(samMember, classId, false, null, null, ids.function)
extractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, null, null, ids.function)
//body
val blockId = tw.getFreshIdLabel<DbBlock>()
@@ -4152,7 +4187,7 @@ open class KotlinFileExtractor(
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction)
// Extract local function as a member
extractFunction(localFunction, id, true, null, listOf())
extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, null, listOf())
return id
}

View File

@@ -4,21 +4,19 @@ import com.github.codeql.utils.*
import com.github.codeql.utils.versions.isRawType
import com.semmle.extractor.java.OdasaOutput
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -49,6 +47,41 @@ open class KotlinUsesExtractor(
TypeResult(fakeKotlinType(), "", "")
)
private data class MethodKey(val className: FqName, val functionName: Name)
private fun makeDescription(className: FqName, functionName: String) = MethodKey(className, Name.guessByFirstCharacter(functionName))
// This essentially mirrors SpecialBridgeMethods.kt, a backend pass which isn't easily available to our extractor.
private val specialFunctions = mapOf(
makeDescription(StandardNames.FqNames.collection, "<get-size>") to "size",
makeDescription(FqName("java.util.Collection"), "<get-size>") to "size",
makeDescription(StandardNames.FqNames.map, "<get-size>") to "size",
makeDescription(FqName("java.util.Map"), "<get-size>") to "size",
makeDescription(StandardNames.FqNames.charSequence.toSafe(), "<get-length>") to "length",
makeDescription(FqName("java.lang.CharSequence"), "<get-length>") to "length",
makeDescription(StandardNames.FqNames.map, "<get-keys>") to "keySet",
makeDescription(FqName("java.util.Map"), "<get-keys>") to "keySet",
makeDescription(StandardNames.FqNames.map, "<get-values>") to "values",
makeDescription(FqName("java.util.Map"), "<get-values>") to "values",
makeDescription(StandardNames.FqNames.map, "<get-entries>") to "entrySet",
makeDescription(FqName("java.util.Map"), "<get-entries>") to "entrySet"
)
private val specialFunctionShortNames = specialFunctions.keys.map { it.functionName }.toSet()
fun getSpecialJvmName(f: IrFunction): String? {
if (specialFunctionShortNames.contains(f.name) && f is IrSimpleFunction) {
f.allOverridden(true).forEach { overriddenFunc ->
overriddenFunc.parentAsClass.fqNameWhenAvailable?.let { parentFqName ->
specialFunctions[MethodKey(parentFqName, f.name)]?.let {
return it
}
}
}
}
return null
}
fun getJvmName(container: IrAnnotationContainer): String? {
for(a: IrConstructorCall in container.annotations) {
val t = a.type
@@ -67,7 +100,7 @@ open class KotlinUsesExtractor(
}
}
}
return null
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
}
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
@@ -122,10 +155,7 @@ open class KotlinUsesExtractor(
}
fun getJavaEquivalentClass(c: IrClass) =
c.fqNameWhenAvailable?.toUnsafe()
?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }
?.let { pluginContext.referenceClass(it.asSingleFqName()) }
?.owner
getJavaEquivalentClassId(c)?.let { pluginContext.referenceClass(it.asSingleFqName()) }?.owner
/**
* Gets a KotlinFileExtractor based on this one, except it attributes locations to the file that declares the given class.
@@ -380,7 +410,7 @@ open class KotlinUsesExtractor(
if (inReceiverContext && globalExtensionState.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses)
extractorWithCSource.extractClassSupertypes(c, classLabel, supertypeMode, true)
extractorWithCSource.extractMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
extractorWithCSource.extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
}
}
@@ -696,8 +726,26 @@ open class KotlinUsesExtractor(
}
when (f) {
getter -> return FunctionNames(getJvmName(getter) ?: JvmAbi.getterName(propName), JvmAbi.getterName(propName))
setter -> return FunctionNames(getJvmName(setter) ?: JvmAbi.setterName(propName), JvmAbi.setterName(propName))
getter -> {
val defaultFunctionName = JvmAbi.getterName(propName)
val defaultDbName = if (getter.visibility == DescriptorVisibilities.PRIVATE && getter.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
// In JVM these functions don't exist, instead the backing field is accessed directly
defaultFunctionName + "\$private"
} else {
defaultFunctionName
}
return FunctionNames(getJvmName(getter) ?: defaultDbName, defaultFunctionName)
}
setter -> {
val defaultFunctionName = JvmAbi.setterName(propName)
val defaultDbName = if (setter.visibility == DescriptorVisibilities.PRIVATE && setter.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
// In JVM these functions don't exist, instead the backing field is accessed directly
defaultFunctionName + "\$private"
} else {
defaultFunctionName
}
return FunctionNames(getJvmName(setter) ?: defaultDbName, defaultFunctionName)
}
else -> {
logger.error(
"Function has a corresponding property, but is neither the getter nor the setter"
@@ -774,7 +822,9 @@ open class KotlinUsesExtractor(
// The type parameters of the function. This does not include type parameters of enclosing classes.
functionTypeParameters: List<IrTypeParameter>,
// The type arguments of enclosing classes of the function.
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?,
// The prefix used in the label. "callable", unless a property label is created, then it's "property".
prefix: String = "callable"
): String {
val parentId = maybeParentId ?: useDeclarationParent(parent, false, classTypeArgsIncludingOuterClasses, true)
val allParams = if (extensionReceiverParameter == null) {
@@ -810,7 +860,7 @@ open class KotlinUsesExtractor(
// method (and presumably that disambiguation is never needed when the method belongs to a parameterized
// instance of a generic class), but as of now I don't know when the raw method would be referred to.
val typeArgSuffix = if (functionTypeParameters.isNotEmpty() && classTypeArgsIncludingOuterClasses.isNullOrEmpty()) "<${functionTypeParameters.size}>" else "";
return "@\"callable;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
}
protected fun IrFunction.isLocalFunction(): Boolean {
@@ -867,17 +917,62 @@ open class KotlinUsesExtractor(
return id
}
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null): Label<out T> {
// 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.
private val expectedMissingEquivalents = setOf(
"kotlin.Boolean", "kotlin.Byte", "kotlin.Char", "kotlin.Double", "kotlin.Float", "kotlin.Int", "kotlin.Long", "kotlin.Number", "kotlin.Short"
)
fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean) =
if (noReplace)
f
else
f.parentClassOrNull?.let { parentClass ->
getJavaEquivalentClass(parentClass)?.let { javaClass ->
if (javaClass != parentClass)
// Look for an exact type match...
javaClass.declarations.find { decl ->
decl is IrFunction &&
decl.name == f.name &&
decl.valueParameters.size == f.valueParameters.size &&
// Note matching by classifier not the whole type so that generic arguments are allowed to differ,
// as they always will for method type parameters occurring in parameter types (e.g. <T> toArray(T[] array)
// Differing only by nullability would also be insignificant if it came up.
decl.valueParameters.zip(f.valueParameters).all { p -> p.first.type.classifierOrNull == p.second.type.classifierOrNull }
} ?:
// Or if there is none, look for the only viable overload
javaClass.declarations.singleOrNull { decl ->
decl is IrFunction &&
decl.name == f.name &&
decl.valueParameters.size == f.valueParameters.size
} ?:
run {
val parentFqName = parentClass.fqNameWhenAvailable?.asString()
if (!expectedMissingEquivalents.contains(parentFqName)) {
logger.warn("Couldn't find a Java equivalent function to $parentFqName.${f.name} in ${javaClass.fqNameWhenAvailable}")
}
null
}
else
null
}
} as IrFunction? ?: f
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
if (f.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(f)
return ids.function.cast<T>()
} else {
return useFunctionCommon<T>(f, getFunctionLabel(f, classTypeArgsIncludingOuterClasses))
val realFunction = kotlinFunctionToJavaEquivalent(f, noReplace)
return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses))
}
}
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) =
useFunctionCommon<T>(f, getFunctionLabel(f, parentId, classTypeArgsIncludingOuterClasses))
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
@@ -941,6 +1036,9 @@ open class KotlinUsesExtractor(
is IrFunction -> {
"{${useFunction<DbMethod>(parent)}}.$cls"
}
is IrField -> {
"{${useField(parent)}}.$cls"
}
else -> {
if (pkg.isEmpty()) cls else "$pkg.$cls"
}
@@ -1111,15 +1209,20 @@ open class KotlinUsesExtractor(
* `parent` is null.
*/
fun getValueParameterLabel(vp: IrValueParameter, parent: Label<out DbCallable>?): String {
val parentId = parent ?: useDeclarationParent(vp.parent, false)
val idx = vp.index
val declarationParent = vp.parent
val parentId = parent ?: useDeclarationParent(declarationParent, false)
val idx = if (declarationParent is IrFunction && declarationParent.extensionReceiverParameter != null)
// For extension functions increase the index to match what the java extractor sees:
vp.index + 1
else
vp.index
if (idx < 0) {
val p = vp.parent
if (p !is IrFunction || p.extensionReceiverParameter != vp) {
// We're not extracting this and this@TYPE parameters of functions:
logger.error("Unexpected negative index for parameter")
}
// We're not extracting this and this@TYPE parameters of functions:
logger.error("Unexpected negative index for parameter")
}
return "@\"params;{$parentId};$idx\""
}
@@ -1140,24 +1243,29 @@ open class KotlinUsesExtractor(
if (parentId == null) {
return null
} else {
return getPropertyLabel(p, parentId)
return getPropertyLabel(p, parentId, null)
}
}
fun getPropertyLabel(p: IrProperty, parentId: Label<out DbElement>) =
"@\"property;{$parentId};${p.name.asString()}\""
private fun getPropertyLabel(p: IrProperty, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): String {
val getter = p.getter
val setter = p.setter
fun useProperty(p: IrProperty): Label<out DbKt_property>? {
val label = getPropertyLabel(p)
if (label == null) {
return null
val func = getter ?: setter
val ext = func?.extensionReceiverParameter
return if (ext == null) {
"@\"property;{$parentId};${p.name.asString()}\""
} else {
return tw.getLabelFor<DbKt_property>(label).also { extractPropertyLaterIfExternalFileMember(p) }
val returnType = getter?.returnType ?: setter?.valueParameters?.singleOrNull()?.type ?: pluginContext.irBuiltIns.unitType
val typeParams = getFunctionTypeParameters(func)
getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, "property")
}
}
fun useProperty(p: IrProperty, parentId: Label<out DbElement>): Label<out DbKt_property> =
tw.getLabelFor<DbKt_property>(getPropertyLabel(p, parentId)).also { extractPropertyLaterIfExternalFileMember(p) }
fun useProperty(p: IrProperty, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): Label<out DbKt_property> =
tw.getLabelFor<DbKt_property>(getPropertyLabel(p, parentId, classTypeArgsIncludingOuterClasses)).also { extractPropertyLaterIfExternalFileMember(p) }
fun getEnumEntryLabel(ee: IrEnumEntry): String {
val parentId = useDeclarationParent(ee.parent, false)

View File

@@ -7,7 +7,9 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
@@ -84,4 +86,7 @@ fun getContainingClassOrSelf(decl: IrDeclaration): IrClass? {
is IrClass -> decl
else -> decl.parentClassOrNull
}
}
}
fun getJavaEquivalentClassId(c: IrClass) =
c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }

View File

@@ -1,6 +1,7 @@
package com.github.codeql.utils
import com.github.codeql.KotlinUsesExtractor
import com.github.codeql.getJavaEquivalentClassId
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.constructedClassType
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -195,13 +197,25 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
typealias TypeSubstitution = (IrType, KotlinUsesExtractor.TypeContext, IrPluginContext) -> IrType
fun matchingTypeParameters(l: IrTypeParameter?, r: IrTypeParameter): Boolean {
if (l === r)
return true
if (l == null)
return false
// Special case: match List's E and MutableList's E, for example, because in the JVM lowering they will map to the same thing.
val lParent = l.parent as? IrClass ?: return false
val rParent = r.parent as? IrClass ?: return false
val lJavaId = getJavaEquivalentClassId(lParent) ?: lParent.classId
return (getJavaEquivalentClassId(rParent) ?: rParent.classId) == lJavaId && l.name == r.name
}
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>): Boolean {
val unspecialisedHere = paramsContainer.typeParameters.zip(args).all { paramAndArg ->
(paramAndArg.second as? IrTypeProjection)?.let {
// Type arg refers to the class' own type parameter?
it.variance == Variance.INVARIANT &&
it.type.classifierOrNull?.owner === paramAndArg.first
matchingTypeParameters(it.type.classifierOrNull?.owner as? IrTypeParameter, paramAndArg.first)
} ?: false
}
val remainingArgs = args.drop(paramsContainer.typeParameters.size)

View File

@@ -143,6 +143,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.JMS
private import semmle.code.java.frameworks.RabbitMQ
private import semmle.code.java.regex.RegexFlowModels
private import semmle.code.java.frameworks.KotlinStdLib
}
private predicate sourceModelCsv(string row) {

View File

@@ -0,0 +1,11 @@
/** Definitions of taint steps in the KotlinStdLib framework */
import java
private import semmle.code.java.dataflow.ExternalFlow
private class KotlinStdLibSummaryCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"kotlin.jvm.internal;ArrayIteratorKt;false;iterator;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value"
}
}

View File

@@ -578,7 +578,7 @@ generic_anonymous.kt:
# 3| 1: [ExprStmt] <Expr>;
# 3| 0: [ClassInstanceExpr] new (...)
# 3| -3: [TypeAccess] Object
# 3| 5: [Method] getX
# 3| 5: [Method] getX$private
# 3| 3: [TypeAccess] new Object(...) { ... }
# 3| 0: [TypeAccess] T
# 3| 5: [BlockStmt] { ... }
@@ -590,8 +590,69 @@ generic_anonymous.kt:
# 7| 5: [BlockStmt] { ... }
# 7| 0: [ReturnStmt] return ...
# 7| 0: [MethodAccess] getMember(...)
# 7| -1: [MethodAccess] getX(...)
# 7| -1: [MethodAccess] getX$private(...)
# 7| -1: [ThisAccess] this
localClassField.kt:
# 0| [CompilationUnit] localClassField
# 1| 1: [Class] A
# 1| 1: [Constructor] A
# 1| 5: [BlockStmt] { ... }
# 1| 0: [SuperConstructorInvocationStmt] super(...)
# 1| 1: [BlockStmt] { ... }
# 2| 0: [ExprStmt] <Expr>;
# 2| 0: [KtInitializerAssignExpr] ...=...
# 2| 0: [VarAccess] x
# 7| 1: [ExprStmt] <Expr>;
# 7| 0: [KtInitializerAssignExpr] ...=...
# 7| 0: [VarAccess] y
# 2| 2: [Method] getX
# 2| 3: [TypeAccess] Object
# 2| 5: [BlockStmt] { ... }
# 2| 0: [ReturnStmt] return ...
# 2| 0: [VarAccess] this.x
# 2| -1: [ThisAccess] this
# 2| 2: [FieldDeclaration] Object x;
# 2| -1: [TypeAccess] Object
# 2| 0: [WhenExpr] when ...
# 2| 0: [WhenBranch] ... -> ...
# 2| 0: [BooleanLiteral] true
# 2| 1: [BlockStmt] { ... }
# 3| 0: [LocalTypeDeclStmt] class ...
# 3| 0: [LocalClass] L
# 3| 1: [Constructor] L
# 3| 5: [BlockStmt] { ... }
# 3| 0: [SuperConstructorInvocationStmt] super(...)
# 3| 1: [BlockStmt] { ... }
# 4| 1: [ExprStmt] <Expr>;
# 4| 0: [ClassInstanceExpr] new L(...)
# 4| -3: [TypeAccess] L
# 2| 1: [WhenBranch] ... -> ...
# 2| 0: [BooleanLiteral] true
# 5| 1: [BlockStmt] { ... }
# 7| 4: [Method] getY
# 7| 3: [TypeAccess] Object
# 7| 5: [BlockStmt] { ... }
# 7| 0: [ReturnStmt] return ...
# 7| 0: [VarAccess] this.y
# 7| -1: [ThisAccess] this
# 7| 4: [FieldDeclaration] Object y;
# 7| -1: [TypeAccess] Object
# 7| 0: [WhenExpr] when ...
# 7| 0: [WhenBranch] ... -> ...
# 7| 0: [BooleanLiteral] true
# 7| 1: [BlockStmt] { ... }
# 8| 0: [LocalTypeDeclStmt] class ...
# 8| 0: [LocalClass] L
# 8| 1: [Constructor] L
# 8| 5: [BlockStmt] { ... }
# 8| 0: [SuperConstructorInvocationStmt] super(...)
# 8| 1: [BlockStmt] { ... }
# 9| 1: [ExprStmt] <Expr>;
# 9| 0: [ClassInstanceExpr] new L(...)
# 9| -3: [TypeAccess] L
# 7| 1: [WhenBranch] ... -> ...
# 7| 0: [BooleanLiteral] true
# 10| 1: [BlockStmt] { ... }
local_anonymous.kt:
# 0| [CompilationUnit] local_anonymous
# 3| 1: [Class] Class1

View File

@@ -37,6 +37,9 @@
| generic_anonymous.kt:0:0:0:0 | Generic_anonymousKt | Generic_anonymousKt | final, public |
| generic_anonymous.kt:1:1:9:1 | Generic | Generic | final, private |
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | <anonymous class> | final, private |
| localClassField.kt:1:1:11:1 | A | A | final, public |
| localClassField.kt:3:9:3:19 | L | A$L | final, private |
| localClassField.kt:8:9:8:19 | L | A$L | final, private |
| local_anonymous.kt:3:1:36:1 | Class1 | LocalAnonymous.Class1 | final, public |
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | <anonymous class> | final, private |
| local_anonymous.kt:11:9:11:24 | | Class1$ | final, private |

View File

@@ -36,6 +36,9 @@ superCall
| classes.kt:129:17:131:17 | super(...) |
| generic_anonymous.kt:1:1:9:1 | super(...) |
| generic_anonymous.kt:3:19:5:3 | super(...) |
| localClassField.kt:1:1:11:1 | super(...) |
| localClassField.kt:3:9:3:19 | super(...) |
| localClassField.kt:8:9:8:19 | super(...) |
| local_anonymous.kt:3:1:36:1 | super(...) |
| local_anonymous.kt:5:16:7:9 | super(...) |
| local_anonymous.kt:11:9:11:24 | super(...) |

View File

@@ -27,7 +27,7 @@
| generic_anonymous.kt:4:20:4:20 | Generic.this | Generic |
| generic_anonymous.kt:4:20:4:20 | getT(...) | T |
| generic_anonymous.kt:7:3:7:22 | T | T |
| generic_anonymous.kt:7:15:7:15 | getX(...) | new Object(...) { ... } |
| generic_anonymous.kt:7:15:7:15 | getX$private(...) | new Object(...) { ... } |
| generic_anonymous.kt:7:15:7:15 | this | Generic |
| generic_anonymous.kt:7:17:7:22 | getMember(...) | T |
| generic_anonymous.kt:11:1:11:56 | String | String |

View File

@@ -2,5 +2,7 @@
| classes.kt:118:9:123:9 | class ... | classes.kt:118:9:123:9 | | classes.kt:117:5:124:5 | fn2 | classes.kt:109:1:136:1 | C1 |
| classes.kt:119:13:121:13 | class ... | classes.kt:119:13:121:13 | Local2 | classes.kt:118:9:123:9 | localFn | classes.kt:109:1:136:1 | C1 |
| classes.kt:129:17:131:17 | class ... | classes.kt:129:17:131:17 | Local3 | classes.kt:128:13:133:13 | fn | classes.kt:127:16:134:9 | new Object(...) { ... } |
| localClassField.kt:3:9:3:19 | class ... | localClassField.kt:3:9:3:19 | L | localClassField.kt:1:1:11:1 | A | localClassField.kt:1:1:11:1 | A |
| localClassField.kt:8:9:8:19 | class ... | localClassField.kt:8:9:8:19 | L | localClassField.kt:1:1:11:1 | A | localClassField.kt:1:1:11:1 | A |
| local_anonymous.kt:11:9:11:24 | class ... | local_anonymous.kt:11:9:11:24 | | local_anonymous.kt:10:5:13:5 | fn2 | local_anonymous.kt:3:1:36:1 | Class1 |
| local_anonymous.kt:25:9:25:27 | class ... | local_anonymous.kt:25:9:25:27 | LocalClass | local_anonymous.kt:24:5:27:5 | fn5 | local_anonymous.kt:3:1:36:1 | Class1 |

View File

@@ -0,0 +1,11 @@
class A {
val x = if (true) {
class L { }
L()
} else {}
val y = if (true) {
class L { }
L()
} else {}
}

View File

@@ -49,6 +49,9 @@
| file://<external>/SuperChain2.class:0:0:0:0 | SuperChain2<T5,String> | file://<external>/SuperChain1.class:0:0:0:0 | SuperChain1<T5,String> |
| generic_anonymous.kt:1:1:9:1 | Generic | file://<external>/Object.class:0:0:0:0 | Object |
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
| localClassField.kt:1:1:11:1 | A | file://<external>/Object.class:0:0:0:0 | Object |
| localClassField.kt:3:9:3:19 | L | file://<external>/Object.class:0:0:0:0 | Object |
| localClassField.kt:8:9:8:19 | L | file://<external>/Object.class:0:0:0:0 | Object |
| local_anonymous.kt:3:1:36:1 | Class1 | file://<external>/Object.class:0:0:0:0 | Object |
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
| local_anonymous.kt:11:9:11:24 | | file://<external>/Object.class:0:0:0:0 | Object |

View File

@@ -12,7 +12,7 @@ commentOwners
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members |
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members |
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:13:17:46 | getMembers |
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:13:17:46 | getMembers$private |
| comments.kt:19:5:22:7 | /**\n * Adds a [member] to this group.\n * @return the new size of the group.\n */ | comments.kt:23:5:26:5 | add |
| comments.kt:35:5:35:34 | /** Medium is in the middle */ | comments.kt:36:5:36:14 | Medium |
| comments.kt:37:5:37:23 | /** This is high */ | comments.kt:38:5:38:11 | High |

View File

@@ -1,2 +1,2 @@
| companion_objects.kt:1:1:6:1 | MyClass | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:3:5:5:5 | MyClassCompanion | final,public,static |
| companion_objects.kt:8:1:13:1 | MyInterface | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | final,public,static |
| companion_objects.kt:1:1:6:1 | MyClass | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:1:1:6:1 | MyClass | final,public,static |
| companion_objects.kt:8:1:13:1 | MyInterface | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:8:1:13:1 | MyInterface | final,public,static |

View File

@@ -5,4 +5,4 @@ where
c.fromSource() and
cco = c.getCompanionObject() and
f = cco.getInstance()
select c, f, cco, concat(f.getAModifier().toString(), ",")
select c, f, cco, f.getDeclaringType(), concat(f.getAModifier().toString(), ",")

View File

@@ -5,4 +5,4 @@
| dc.kt:0:0:0:0 | times(...) | Int.times |
| dc.kt:0:0:0:0 | toString(...) | Arrays.toString |
| dc.kt:0:0:0:0 | toString(...) | Arrays.toString |
| dc.kt:1:1:1:71 | super(...) | Any.Any |
| dc.kt:1:1:1:71 | super(...) | Object.Object |

View File

@@ -0,0 +1,22 @@
public final class C1 {
public final String taint(String t) {
return t;
}
public final void sink(Object a) {
}
public final void test() {
String[] l = new String[]{this.taint("a"), ""};
this.sink(l);
this.sink(l[0]);
for(int i = 0; i < l.length; i++) {
this.sink(l[i]);
}
for (String s : l) {
this.sink(s);
}
}
}

View File

@@ -0,0 +1,18 @@
class C2 {
fun taint(t: String): String {
return t
}
fun sink(a: Any?) {}
fun test() {
val l = arrayOf(taint("a"), "")
sink(l)
sink(l[0])
for (i in l.indices) {
sink(l[i])
}
for (s in l) {
sink(s)
}
}
}

View File

@@ -0,0 +1,8 @@
| C1.java:10:44:10:46 | "a" | C1.java:11:17:11:17 | l |
| C1.java:10:44:10:46 | "a" | C1.java:12:17:12:20 | ...[...] |
| C1.java:10:44:10:46 | "a" | C1.java:15:20:15:23 | ...[...] |
| C1.java:10:44:10:46 | "a" | C1.java:19:20:19:20 | s |
| C2.kt:8:32:8:32 | a | C2.kt:9:14:9:14 | l |
| C2.kt:8:32:8:32 | a | C2.kt:10:14:10:17 | ...[...] |
| C2.kt:8:32:8:32 | a | C2.kt:12:18:12:21 | ...[...] |
| C2.kt:8:32:8:32 | a | C2.kt:15:18:15:18 | s |

View File

@@ -0,0 +1,19 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.ExternalFlow
class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest:foreach-array-iterator" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("taint")
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
}
}
from DataFlow::Node src, DataFlow::Node sink, Conf conf
where conf.hasFlow(src, sink)
select src, sink

View File

@@ -1717,86 +1717,6 @@
| exprs.kt:268:3:268:9 | updated | exprs.kt:261:1:270:1 | inPlaceOperators | VarAccess |
| exprs.kt:268:3:268:14 | ...%=... | exprs.kt:261:1:270:1 | inPlaceOperators | AssignRemExpr |
| exprs.kt:268:14:268:14 | 1 | exprs.kt:261:1:270:1 | inPlaceOperators | IntegerLiteral |
| file:///!unknown-binary-location/SomePredicate.class:0:0:0:0 | T | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/SomePredicate.class:0:0:0:0 | boolean | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function0.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function1.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function1.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P23 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P23 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P24 | file://:0:0:0:0 | <none> | TypeAccess |
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:1:1:1:46 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:1:26:1:37 | Function0<Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:1:26:1:37 | Integer | file://:0:0:0:0 | <none> | TypeAccess |

View File

@@ -0,0 +1,5 @@
class A {
void method() {
ExtensionsKt.someFun(new SomeClass(), "");
}
}

View File

@@ -1,3 +1,5 @@
| A.java:3:9:3:49 | someFun(...) | A.java:3:9:3:20 | ExtensionsKt | A.java:3:30:3:44 | new SomeClass(...) |
| A.java:3:9:3:49 | someFun(...) | A.java:3:9:3:20 | ExtensionsKt | A.java:3:47:3:48 | "" |
| extensions.kt:21:17:21:38 | someClassMethod(...) | extensions.kt:21:5:21:15 | new SomeClass(...) | extensions.kt:21:34:21:36 | foo |
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:5:22:15 | new SomeClass(...) |
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:26:22:28 | foo |

View File

@@ -1,3 +1,4 @@
| A.java:2:10:2:15 | method | file://:0:0:0:0 | void |
| extensions.kt:3:5:3:38 | someClassMethod | file://:0:0:0:0 | void |
| extensions.kt:6:5:6:41 | anotherClassMethod | file://:0:0:0:0 | void |
| extensions.kt:9:1:9:36 | someFun | file://:0:0:0:0 | void |

View File

@@ -1,7 +1,9 @@
parametersWithArgs
| extensions.kt:3:25:3:34 | p1 | 0 | extensions.kt:21:34:21:36 | foo |
| extensions.kt:6:28:6:37 | p1 | 0 | extensions.kt:25:40:25:42 | foo |
| extensions.kt:9:5:9:13 | <this> | 0 | A.java:3:30:3:44 | new SomeClass(...) |
| extensions.kt:9:5:9:13 | <this> | 0 | extensions.kt:22:5:22:15 | new SomeClass(...) |
| extensions.kt:9:23:9:32 | p1 | 1 | A.java:3:47:3:48 | "" |
| extensions.kt:9:23:9:32 | p1 | 1 | extensions.kt:22:26:22:28 | foo |
| extensions.kt:10:5:10:16 | <this> | 0 | extensions.kt:26:5:26:18 | new AnotherClass(...) |
| extensions.kt:10:29:10:38 | p1 | 1 | extensions.kt:26:32:26:34 | foo |

View File

@@ -3,8 +3,8 @@
| Test.java:25:5:25:16 | hashCode(...) | hashCode | Object |
| Test.java:26:5:26:17 | inheritMe(...) | inheritMe | Test |
| Test.java:28:5:28:34 | inheritedInterfaceMethodJ(...) | inheritedInterfaceMethodJ | ParentIf |
| Test.kt:23:7:23:16 | toString(...) | toString | Any |
| Test.kt:24:7:24:15 | equals(...) | equals | Any |
| Test.kt:25:7:25:16 | hashCode(...) | hashCode | Any |
| Test.kt:23:7:23:16 | toString(...) | toString | Object |
| Test.kt:24:7:24:15 | equals(...) | equals | Object |
| Test.kt:25:7:25:16 | hashCode(...) | hashCode | Object |
| Test.kt:26:7:26:17 | inheritMe(...) | inheritMe | TestKt |
| Test.kt:28:9:28:35 | inheritedInterfaceMethodK(...) | inheritedInterfaceMethodK | ParentIf |

View File

@@ -0,0 +1,2 @@
| Integer |
| Object |

View File

@@ -0,0 +1 @@
fun test(m: Map<Int, Int>) = m.getOrDefault(1, 2)

View File

@@ -0,0 +1,4 @@
import java
from MethodAccess ma
select ma.getCallee().getAParameter().getType().toString()

View File

@@ -0,0 +1 @@
| clinit.kt:0:0:0:0 | <clinit> | file://:0:0:0:0 | void |

View File

@@ -0,0 +1,3 @@
package foo.bar
var topLevelInt: Int = 0

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.getName() = "<clinit>"
select m, m.getReturnType()

View File

@@ -1,3 +1,17 @@
| clinit.kt:3:1:3:24 | ...=... | AssignExpr |
| clinit.kt:3:1:3:24 | ...=... | KtInitializerAssignExpr |
| clinit.kt:3:1:3:24 | <set-?> | VarAccess |
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
| clinit.kt:3:1:3:24 | Unit | TypeAccess |
| clinit.kt:3:1:3:24 | int | TypeAccess |
| clinit.kt:3:1:3:24 | int | TypeAccess |
| clinit.kt:3:1:3:24 | int | TypeAccess |
| clinit.kt:3:24:3:24 | 0 | IntegerLiteral |
| methods2.kt:4:1:5:1 | Unit | TypeAccess |
| methods2.kt:4:26:4:31 | int | TypeAccess |
| methods2.kt:4:34:4:39 | int | TypeAccess |

View File

@@ -1,4 +1,7 @@
methods
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:0:0:0:0 | <clinit> | <clinit>() | |
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | getTopLevelInt | getTopLevelInt() | public, static |
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | setTopLevelInt | setTopLevelInt(int) | public, static |
| methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | public, static |
| methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | public |
| methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public, static |

View File

@@ -1,3 +1,4 @@
| clinit.kt:3:1:3:24 | setTopLevelInt | clinit.kt:3:1:3:24 | <set-?> | 0 |
| methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:26:4:31 | x | 0 |
| methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:34:4:39 | y | 1 |
| methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:27:8:32 | x | 0 |

View File

@@ -2,7 +2,7 @@
| modifiers.kt:1:6:25:1 | X | Constructor | public |
| modifiers.kt:2:5:2:21 | a | Field | private |
| modifiers.kt:2:5:2:21 | a | Property | private |
| modifiers.kt:2:13:2:21 | getA | Method | private |
| modifiers.kt:2:13:2:21 | getA$private | Method | private |
| modifiers.kt:3:5:3:23 | b | Field | private |
| modifiers.kt:3:5:3:23 | b | Property | protected |
| modifiers.kt:3:15:3:23 | getB | Method | protected |

View File

@@ -0,0 +1 @@
class Ext : A<String>("Hello") { }

View File

@@ -0,0 +1,18 @@
| file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> | file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> |
| file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> | file:///!unknown-binary-location/A.class:0:0:0:0 | getAnonType |
| file:///!unknown-binary-location/If.class:0:0:0:0 | If<String> | file:///!unknown-binary-location/If.class:0:0:0:0 | getX |
| file:///!unknown-binary-location/If.class:0:0:0:0 | If<T> | file:///!unknown-binary-location/If.class:0:0:0:0 | getX |
| other.kt:1:1:1:34 | Ext | other.kt:1:1:1:34 | Ext |
| test.kt:0:0:0:0 | TestKt | test.kt:19:1:19:38 | user |
| test.kt:1:1:5:1 | If | test.kt:3:3:3:11 | getX |
| test.kt:7:1:17:1 | A | test.kt:7:6:17:1 | A |
| test.kt:7:1:17:1 | A | test.kt:9:3:11:3 | anonType |
| test.kt:7:1:17:1 | A | test.kt:9:3:11:3 | getAnonType |
| test.kt:7:1:17:1 | A | test.kt:13:3:15:3 | privateAnonType |
| test.kt:7:1:17:1 | A | test.kt:13:11:15:3 | getPrivateAnonType$private |
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:9:18:11:3 | |
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:10:5:10:22 | x |
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:10:14:10:22 | getX |
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:13:33:15:3 | |
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:14:5:14:22 | x |
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:14:14:14:22 | getX |

View File

@@ -0,0 +1,19 @@
interface If<T> {
val x : T
}
open class A<T>(t: T) {
val anonType = object : If<T> {
override val x = t
}
private val privateAnonType = object : If<T> {
override val x = t
}
}
fun user(x: A<String>) = x.anonType.x

View File

@@ -0,0 +1,5 @@
import java
from ClassOrInterface ci, Member m
where m = ci.getAMember() and ci.getSourceDeclaration().fromSource()
select ci, m

View File

@@ -20,6 +20,8 @@ fieldDeclarations
| properties.kt:38:5:38:34 | int internalProp; | properties.kt:38:5:38:34 | internalProp | 0 |
| properties.kt:67:1:67:23 | int constVal; | properties.kt:67:1:67:23 | constVal | 0 |
| properties.kt:70:5:70:16 | int prop; | properties.kt:70:5:70:16 | prop | 0 |
| properties.kt:84:5:84:29 | int data; | properties.kt:84:5:84:29 | data | 0 |
| properties.kt:92:5:93:18 | int data; | properties.kt:92:5:93:18 | data | 0 |
#select
| properties.kt:2:27:2:50 | constructorProp | properties.kt:2:27:2:50 | getConstructorProp | file://:0:0:0:0 | <none> | properties.kt:2:27:2:50 | constructorProp | public |
| properties.kt:2:53:2:83 | mutableConstructorProp | properties.kt:2:53:2:83 | getMutableConstructorProp | properties.kt:2:53:2:83 | setMutableConstructorProp | properties.kt:2:53:2:83 | mutableConstructorProp | public |
@@ -40,9 +42,13 @@ fieldDeclarations
| properties.kt:30:5:31:29 | overrideGetterUseField | properties.kt:31:13:31:29 | getOverrideGetterUseField | properties.kt:30:5:31:29 | setOverrideGetterUseField | properties.kt:30:5:31:29 | overrideGetterUseField | public |
| properties.kt:32:5:33:29 | useField | properties.kt:33:13:33:29 | getUseField | file://:0:0:0:0 | <none> | properties.kt:32:5:33:29 | useField | public |
| properties.kt:34:5:34:36 | lateInitVar | properties.kt:34:14:34:36 | getLateInitVar | properties.kt:34:14:34:36 | setLateInitVar | properties.kt:34:5:34:36 | lateInitVar | public |
| properties.kt:35:5:35:32 | privateProp | properties.kt:35:13:35:32 | getPrivateProp | file://:0:0:0:0 | <none> | properties.kt:35:5:35:32 | privateProp | private |
| properties.kt:35:5:35:32 | privateProp | properties.kt:35:13:35:32 | getPrivateProp$private | file://:0:0:0:0 | <none> | properties.kt:35:5:35:32 | privateProp | private |
| properties.kt:36:5:36:36 | protectedProp | properties.kt:36:15:36:36 | getProtectedProp | file://:0:0:0:0 | <none> | properties.kt:36:5:36:36 | protectedProp | protected |
| properties.kt:37:5:37:30 | publicProp | properties.kt:37:12:37:30 | getPublicProp | file://:0:0:0:0 | <none> | properties.kt:37:5:37:30 | publicProp | public |
| properties.kt:38:5:38:34 | internalProp | properties.kt:38:14:38:34 | getInternalProp | file://:0:0:0:0 | <none> | properties.kt:38:5:38:34 | internalProp | internal |
| properties.kt:67:1:67:23 | constVal | properties.kt:67:7:67:23 | getConstVal | file://:0:0:0:0 | <none> | properties.kt:67:1:67:23 | constVal | public |
| properties.kt:70:5:70:16 | prop | properties.kt:70:5:70:16 | getProp | file://:0:0:0:0 | <none> | properties.kt:70:5:70:16 | prop | public |
| properties.kt:78:1:79:13 | x | properties.kt:79:5:79:13 | getX | file://:0:0:0:0 | <none> | file://:0:0:0:0 | <none> | public |
| properties.kt:80:1:81:13 | x | properties.kt:81:5:81:13 | getX | file://:0:0:0:0 | <none> | file://:0:0:0:0 | <none> | public |
| properties.kt:84:5:84:29 | data | properties.kt:84:13:84:29 | getData$private | properties.kt:84:13:84:29 | setData$private | properties.kt:84:5:84:29 | data | private |
| properties.kt:92:5:93:18 | data | properties.kt:93:9:93:18 | getData | properties.kt:92:13:93:18 | setData$private | properties.kt:92:5:93:18 | data | private |

View File

@@ -73,3 +73,26 @@ class C<T> {
println(c.prop)
}
}
val Int.x : Int
get() = 5
val Double.x : Int
get() = 5
class A {
private var data: Int = 0
fun setData(p: Int) {
data = p
}
}
class B {
private var data: Int = 5
get() = 42
fun setData(p: Int) {
data = p
}
}

View File

@@ -11,7 +11,7 @@ reflection.kt:
# 47| 0: [MethodAccess] get(...)
# 47| -1: [ExtensionReceiverAccess] this
# 47| 0: [SubExpr] ... - ...
# 47| 0: [MethodAccess] getLength(...)
# 47| 0: [MethodAccess] length(...)
# 47| -1: [ExtensionReceiverAccess] this
# 47| 1: [IntegerLiteral] 1
# 49| 2: [Method] fn2

View File

@@ -0,0 +1,9 @@
| test.kt:1:84:1:89 | length(...) | length |
| test.kt:1:97:1:100 | size(...) | size |
| test.kt:1:108:1:111 | size(...) | size |
| test.kt:1:119:1:122 | keySet(...) | keySet |
| test.kt:1:124:1:127 | size(...) | size |
| test.kt:1:135:1:140 | values(...) | values |
| test.kt:1:142:1:145 | size(...) | size |
| test.kt:1:153:1:159 | entrySet(...) | entrySet |
| test.kt:1:161:1:164 | size(...) | size |

View File

@@ -0,0 +1 @@
fun test(cs: CharSequence, col: Collection<String>, map: Map<String, String>) = cs.length + col.size + map.size + map.keys.size + map.values.size + map.entries.size

View File

@@ -0,0 +1,4 @@
import java
from MethodAccess ma
select ma, ma.getCallee().toString()

View File

@@ -1,13 +1,13 @@
| this.kt:2:1:58:1 | super(...) | Any |
| this.kt:3:5:53:5 | super(...) | Any |
| this.kt:2:1:58:1 | super(...) | Object |
| this.kt:3:5:53:5 | super(...) | Object |
| this.kt:9:66:17:13 | ...->... | |
| this.kt:9:66:17:13 | super(...) | Any |
| this.kt:9:66:17:13 | super(...) | Object |
| this.kt:12:82:16:17 | ...->... | |
| this.kt:12:82:16:17 | super(...) | Any |
| this.kt:12:82:16:17 | super(...) | Object |
| this.kt:19:42:21:13 | ...->... | |
| this.kt:19:42:21:13 | super(...) | Any |
| this.kt:19:42:21:13 | super(...) | Object |
| this.kt:23:30:25:13 | ...->... | |
| this.kt:23:30:25:13 | super(...) | Any |
| this.kt:23:30:25:13 | super(...) | Object |
| this.kt:36:13:36:25 | topLevelFun(...) | topLevelFun |
| this.kt:37:13:37:22 | outerFun(...) | outerFun |
| this.kt:38:13:38:22 | innerFun(...) | innerFun |
@@ -19,5 +19,5 @@
| this.kt:44:18:44:35 | topLevelInnerFun(...) | topLevelInnerFun |
| this.kt:45:18:45:32 | outerInnerFun(...) | outerInnerFun |
| this.kt:46:18:46:40 | topLevelOuterInnerFun(...) | topLevelOuterInnerFun |
| this.kt:64:1:65:1 | super(...) | Any |
| this.kt:67:1:68:1 | super(...) | Any |
| this.kt:64:1:65:1 | super(...) | Object |
| this.kt:67:1:68:1 | super(...) | Object |

View File

@@ -1406,7 +1406,6 @@
| ListIterator | GenericType, Interface, ParameterizedType |
| ListIterator<> | Interface, RawType |
| ListIterator<E> | Interface, ParameterizedType |
| ListIterator<T> | Interface, ParameterizedType |
| LoadOperation | GenericType, Interface, ParameterizedType |
| LoadOperation<> | Interface, RawType |
| LoadOperation<ByteBuffer,V,E,S> | Interface, ParameterizedType |