Merge branch main into rc/3.6

This commit is contained in:
Edoardo Pirovano
2022-06-21 11:15:25 +01:00
1296 changed files with 64800 additions and 9671 deletions

View File

@@ -59,7 +59,7 @@ okhttp3,2,,47,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,22,25
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.io,93,2,565,,78,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,2,551,14
org.apache.commons.io,104,,561,,89,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,547,14
org.apache.commons.jexl2,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.commons.jexl3,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,131
1 package sink source summary sink:bean-validation sink:create-file sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:url-open-stream sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-widget source:contentprovider source:remote summary:taint summary:value
59 org.apache.commons.codec 6 6
60 org.apache.commons.collections 800 17 783
61 org.apache.commons.collections4 800 17 783
62 org.apache.commons.io 93 104 2 565 561 78 89 15 2 551 547 14
63 org.apache.commons.jexl2 15 15
64 org.apache.commons.jexl3 15 15
65 org.apache.commons.lang3 424 293 131

View File

@@ -9,7 +9,7 @@ Java framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE022` :sub:`Path injection`,`CWE036` :sub:`Path traversal`,`CWE079` :sub:`Cross-site scripting`,`CWE089` :sub:`SQL injection`,`CWE090` :sub:`LDAP injection`,`CWE094` :sub:`Code injection`,`CWE319` :sub:`Cleartext transmission`
Android,``android.*``,46,424,108,,,3,67,,,
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,,
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,2,565,93,78,,,,,,15
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,561,104,89,,,,,,15
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,424,,,,,,,,
`Apache Commons Text <https://commons.apache.org/proper/commons-text/>`_,``org.apache.commons.text``,,272,,,,,,,,
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
@@ -19,5 +19,5 @@ Java framework & library support
Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,476,101,,,,19,14,,29
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin.jvm.internal``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,395,932,,,,14,18,,3
Totals,,213,6414,1463,106,6,10,107,33,1,84
Totals,,211,6410,1474,117,6,10,107,33,1,84

View File

@@ -97,19 +97,19 @@ def compile_to_dir(srcs, classpath, java_classpath, output):
'-classpath', os.path.pathsep.join([output, classpath, java_classpath])] + [s for s in srcs if s.endswith(".java")])
def compile_to_jar(srcs, classpath, java_classpath, output):
builddir = 'build/classes'
def compile_to_jar(build_dir, srcs, classpath, java_classpath, output):
class_dir = build_dir + '/classes'
if os.path.exists(builddir):
shutil.rmtree(builddir)
os.makedirs(builddir)
if os.path.exists(class_dir):
shutil.rmtree(class_dir)
os.makedirs(class_dir)
compile_to_dir(srcs, classpath, java_classpath, builddir)
compile_to_dir(srcs, classpath, java_classpath, class_dir)
run_process(['jar', 'cf', output,
'-C', builddir, '.',
'-C', class_dir, '.',
'-C', 'src/main/resources', 'META-INF'])
shutil.rmtree(builddir)
shutil.rmtree(class_dir)
def find_sources(path):
@@ -166,26 +166,28 @@ def transform_to_embeddable(srcs):
f.write(content)
def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output, tmp_dir, version):
def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output, build_dir, version):
classpath = patterns_to_classpath(dependency_folder, jars)
java_classpath = patterns_to_classpath(dependency_folder, java_jars)
if os.path.exists(tmp_dir):
shutil.rmtree(tmp_dir)
shutil.copytree('src', tmp_dir)
tmp_src_dir = build_dir + '/temp_src'
if os.path.exists(tmp_src_dir):
shutil.rmtree(tmp_src_dir)
shutil.copytree('src', tmp_src_dir)
for v in kotlin_plugin_versions.many_versions:
if v != version:
d = tmp_dir + '/main/kotlin/utils/versions/v_' + v.replace('.', '_')
d = tmp_src_dir + '/main/kotlin/utils/versions/v_' + v.replace('.', '_')
shutil.rmtree(d)
srcs = find_sources(tmp_dir)
srcs = find_sources(tmp_src_dir)
transform_to_embeddable(srcs)
compile_to_jar(srcs, classpath, java_classpath, output)
compile_to_jar(build_dir, srcs, classpath, java_classpath, output)
shutil.rmtree(tmp_dir)
shutil.rmtree(tmp_src_dir)
def compile_embeddable(version):
@@ -194,7 +196,7 @@ def compile_embeddable(version):
kotlin_dependency_folder,
transform_to_embeddable,
'codeql-extractor-kotlin-embeddable-%s.jar' % (version),
'build/temp_src',
'build_embeddable_' + version,
version)
@@ -204,7 +206,7 @@ def compile_standalone(version):
kotlin_dependency_folder,
lambda srcs: None,
'codeql-extractor-kotlin-standalone-%s.jar' % (version),
'build/temp_src',
'build_standalone_' + version,
version)
if args.single_version:

View File

@@ -4,10 +4,14 @@ import java.lang.reflect.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.github.codeql.Logger;
import static com.github.codeql.ClassNamesKt.getIrDeclBinaryName;
@@ -547,6 +551,51 @@ public class OdasaOutput {
(tcv.majorVersion == majorVersion && tcv.minorVersion == minorVersion &&
tcv.lastModified < lastModified);
}
private static Map<String, Map<String, Long>> jarFileEntryTimeStamps = new HashMap<>();
private static Map<String, Long> getZipFileEntryTimeStamps(String path, Logger log) {
try {
Map<String, Long> result = new HashMap<>();
ZipFile zf = new ZipFile(path);
Enumeration<? extends ZipEntry> entries = zf.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
result.put(ze.getName(), ze.getLastModifiedTime().toMillis());
}
return result;
} catch(IOException e) {
log.warn("Failed to get entry timestamps from " + path, e);
return null;
}
}
private static long getVirtualFileTimeStamp(VirtualFile vf, Logger log) {
if (vf.getFileSystem().getProtocol().equals("jar")) {
String[] parts = vf.getPath().split("!/");
if (parts.length == 2) {
String jarFilePath = parts[0];
String entryPath = parts[1];
if (!jarFileEntryTimeStamps.containsKey(jarFilePath)) {
jarFileEntryTimeStamps.put(jarFilePath, getZipFileEntryTimeStamps(jarFilePath, log));
}
Map<String, Long> entryTimeStamps = jarFileEntryTimeStamps.get(jarFilePath);
if (entryTimeStamps != null) {
Long entryTimeStamp = entryTimeStamps.get(entryPath);
if (entryTimeStamp != null)
return entryTimeStamp;
else
log.warn("Couldn't find timestamp for jar file " + jarFilePath + " entry " + entryPath);
}
} else {
log.warn("Expected JAR-file path " + vf.getPath() + " to have exactly one '!/' separator");
}
}
// For all files except for jar files, and a fallback in case of I/O problems reading a jar file:
return vf.getTimeStamp();
}
private static TrapClassVersion fromSymbol(IrDeclaration sym, Logger log) {
VirtualFile vf = sym instanceof IrClass ? getIrClassVirtualFile((IrClass)sym) :
sym.getParent() instanceof IrClass ? getIrClassVirtualFile((IrClass)sym.getParent()) :
@@ -583,7 +632,7 @@ public class OdasaOutput {
};
(new ClassReader(vf.contentsToByteArray())).accept(versionGetter, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return new TrapClassVersion(versionStore[0] & 0xffff, versionStore[0] >> 16, vf.getTimeStamp(), "kotlin");
return new TrapClassVersion(versionStore[0] & 0xffff, versionStore[0] >> 16, getVirtualFileTimeStamp(vf, log), "kotlin");
}
catch(IllegalAccessException e) {
log.warn("Failed to read class file version information", e);

View File

@@ -19,6 +19,9 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
val externalDeclsDone = HashSet<IrDeclaration>()
val externalDeclWorkList = ArrayList<Pair<IrDeclaration, String>>()
val propertySignature = ";property"
val fieldSignature = ";field"
fun extractLater(d: IrDeclaration, signature: String): Boolean {
if (d !is IrClass && !isExternalFileClassMember(d)) {
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
@@ -28,13 +31,8 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
if (ret) externalDeclWorkList.add(Pair(d, signature))
return ret
}
val propertySignature = ";property"
val fieldSignature = ";field"
fun extractLater(p: IrProperty) = extractLater(p, propertySignature)
fun extractLater(f: IrField) = extractLater(f, fieldSignature)
fun extractLater(c: IrClass) = extractLater(c, "")
fun extractExternalClasses() {

View File

@@ -165,7 +165,7 @@ class KotlinExtractorGlobalState {
// doesn't have a map as that plugin doesn't generate them. If and when these are used more widely additional maps
// should be added here.
val syntheticToRealClassMap = HashMap<IrClass, IrClass?>()
val syntheticToRealFunctionMap = HashMap<IrSimpleFunction, IrSimpleFunction?>()
val syntheticToRealFunctionMap = HashMap<IrFunction, IrFunction?>()
val syntheticToRealFieldMap = HashMap<IrField, IrField?>()
}

View File

@@ -19,7 +19,13 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaMethod
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.io.Closeable
import java.util.*
@@ -135,7 +141,7 @@ open class KotlinFileExtractor(
Unit
}
is IrField -> {
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
val parentId = useDeclarationParent(getFieldParent(declaration), false)?.cast<DbReftype>()
if (parentId != null) {
extractField(declaration, parentId)
}
@@ -171,7 +177,7 @@ open class KotlinFileExtractor(
}
}
fun extractTypeParameter(tp: IrTypeParameter, apparentIndex: Int): Label<out DbTypevariable>? {
fun extractTypeParameter(tp: IrTypeParameter, apparentIndex: Int, javaTypeParameter: JavaTypeParameter?): Label<out DbTypevariable>? {
with("type parameter", tp) {
val parentId = getTypeParameterParentLabel(tp) ?: return null
val id = tw.getLabelFor<DbTypevariable>(getTypeParameterLabel(tp))
@@ -183,10 +189,21 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(tp)
tw.writeHasLocation(id, locId)
// Annoyingly, we have no obvious way to pair up the bounds of an IrTypeParameter and a JavaTypeParameter
// because JavaTypeParameter provides a Collection not an ordered list, so we can only do our best here:
fun tryGetJavaBound(idx: Int) =
when(tp.superTypes.size) {
1 -> javaTypeParameter?.upperBounds?.singleOrNull()
else -> (javaTypeParameter?.upperBounds as? List)?.getOrNull(idx)
}
tp.superTypes.forEachIndexed { boundIdx, bound ->
if(!(bound.isAny() || bound.isNullableAny())) {
tw.getLabelFor<DbTypebound>("@\"bound;$boundIdx;{$id}\"") {
tw.writeTypeBounds(it, useType(bound).javaResult.id.cast<DbReftype>(), boundIdx, id)
// Note we don't look for @JvmSuppressWildcards here because it doesn't seem to have any impact
// on kotlinc adding wildcards to type parameter bounds.
val boundWithWildcards = addJavaLoweringWildcards(bound, true, tryGetJavaBound(tp.index))
tw.writeTypeBounds(it, useType(boundWithWildcards).javaResult.id.cast<DbReftype>(), boundIdx, id)
}
}
}
@@ -382,7 +399,9 @@ open class KotlinFileExtractor(
extractEnclosingClass(c, id, locId, listOf())
c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx) }
val javaClass = (c.source as? JavaSourceElement)?.javaElement as? JavaClass
c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx, javaClass?.typeParameters?.getOrNull(idx)) }
if (extractDeclarations) {
c.declarations.map { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) }
if (extractStaticInitializer)
@@ -491,17 +510,25 @@ open class KotlinFileExtractor(
private fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label<out DbCallable>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, extractTypeAccess: Boolean, locOverride: Label<DbLocation>? = null): TypeResults {
with("value parameter", vp) {
val location = locOverride ?: getLocation(vp, classTypeArgsIncludingOuterClasses)
val maybeErasedType = (vp.parent as? IrFunction)?.let {
if (overridesCollectionsMethodWithAlteredParameterTypes(it))
eraseCollectionsMethodParameterType(vp.type, it.name.asString(), idx)
else
null
} ?: vp.type
val javaType = (vp.parent as? IrFunction)?.let { getJavaCallable(it)?.let { jCallable -> getJavaValueParameterType(jCallable, idx) } }
val typeWithWildcards = addJavaLoweringWildcards(maybeErasedType, !hasWildcardSuppressionAnnotation(vp), javaType)
val substitutedType = typeSubstitution?.let { it(typeWithWildcards, TypeContext.OTHER, pluginContext) } ?: typeWithWildcards
val id = useValueParameter(vp, parent)
if (extractTypeAccess) {
extractTypeAccessRecursive(typeSubstitution?.let { it(vp.type, TypeContext.OTHER, pluginContext) } ?: vp.type, location, id, -1)
extractTypeAccessRecursive(substitutedType, location, id, -1)
}
return extractValueParameter(id, vp.type, vp.name.asString(), location, parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
}
}
private fun extractValueParameter(id: Label<out DbParam>, t: IrType, name: String, locId: Label<DbLocation>, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, paramSourceDeclaration: Label<out DbParam>, isVararg: Boolean): TypeResults {
val substitutedType = typeSubstitution?.let { it(t, TypeContext.OTHER, pluginContext) } ?: t
val type = useType(substitutedType)
private fun extractValueParameter(id: Label<out DbParam>, t: IrType, name: String, locId: Label<DbLocation>, parent: Label<out DbCallable>, idx: Int, paramSourceDeclaration: Label<out DbParam>, isVararg: Boolean): TypeResults {
val type = useType(t)
tw.writeParams(id, type.javaResult.id, idx, parent, paramSourceDeclaration)
tw.writeParamsKotlinType(id, type.kotlinResult.id)
tw.writeHasLocation(id, locId)
@@ -524,7 +551,10 @@ open class KotlinFileExtractor(
pluginContext.irBuiltIns.unitType,
extensionReceiverParameter = null,
functionTypeParameters = listOf(),
classTypeArgsIncludingOuterClasses = listOf()
classTypeArgsIncludingOuterClasses = listOf(),
overridesCollectionsMethod = false,
javaSignature = null,
addParameterWildcardsByDefault = false
)
val clinitId = tw.getLabelFor<DbMethod>(clinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
@@ -653,17 +683,18 @@ open class KotlinFileExtractor(
}
}
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null, locOverride: Label<DbLocation>? = null) =
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) =
if (isFake(f))
null
else
forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses, idOverride, locOverride)
forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses, null, null)
fun forceExtractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null, locOverride: Label<DbLocation>? = null): Label<out DbCallable> {
fun forceExtractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>?, locOverride: Label<DbLocation>?): Label<out DbCallable> {
with("function", f) {
DeclarationStackAdjuster(f).use {
getFunctionTypeParameters(f).mapIndexed { idx, tp -> extractTypeParameter(tp, idx) }
val javaCallable = getJavaCallable(f)
getFunctionTypeParameters(f).mapIndexed { idx, tp -> extractTypeParameter(tp, idx, (javaCallable as? JavaTypeParameterListOwner)?.typeParameters?.getOrNull(idx)) }
val id =
idOverride
@@ -697,16 +728,17 @@ open class KotlinFileExtractor(
val paramsSignature = allParamTypes.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature!! }
val substReturnType = typeSubstitution?.let { it(f.returnType, TypeContext.RETURN, pluginContext) } ?: f.returnType
val adjustedReturnType = addJavaLoweringWildcards(getAdjustedReturnType(f), false, (javaCallable as? JavaMethod)?.returnType)
val substReturnType = typeSubstitution?.let { it(adjustedReturnType, TypeContext.RETURN, pluginContext) } ?: adjustedReturnType
val locId = locOverride ?: getLocation(f, classTypeArgsIncludingOuterClasses)
if (f.symbol is IrConstructorSymbol) {
val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
val shortName = when {
f.returnType.isAnonymous -> ""
adjustedReturnType.isAnonymous -> ""
typeSubstitution != null -> useType(substReturnType).javaResult.shortName
else -> f.returnType.classFqName?.shortName()?.asString() ?: f.name.asString()
else -> adjustedReturnType.classFqName?.shortName()?.asString() ?: f.name.asString()
}
val constrId = id.cast<DbConstructor>()
tw.writeConstrs(constrId, shortName, "$shortName$paramsSignature", unitType.javaResult.id, parentId, sourceDeclaration.cast<DbConstructor>())
@@ -759,7 +791,8 @@ open class KotlinFileExtractor(
with("field", f) {
DeclarationStackAdjuster(f).use {
declarationStack.push(f)
return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
val fNameSuffix = getExtensionReceiverType(f)?.let { it.classFqName?.asString()?.replace(".", "$$") } ?: ""
return extractField(useField(f), "${f.name.asString()}$fNameSuffix", f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
}
}
}
@@ -829,10 +862,13 @@ open class KotlinFileExtractor(
}
if (bf != null && extractBackingField) {
val fieldId = extractField(bf, parentId)
tw.writeKtPropertyBackingFields(id, fieldId)
if (p.isDelegated) {
tw.writeKtPropertyDelegates(id, fieldId)
val fieldParentId = useDeclarationParent(getFieldParent(bf), false)
if (fieldParentId != null) {
val fieldId = extractField(bf, fieldParentId.cast())
tw.writeKtPropertyBackingFields(id, fieldId)
if (p.isDelegated) {
tw.writeKtPropertyDelegates(id, fieldId)
}
}
}
@@ -1391,12 +1427,6 @@ open class KotlinFileExtractor(
result
}
val javaLangObject by lazy {
val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner
result?.let { extractExternalClassLater(it) }
result
}
val objectCloneMethod by lazy {
val result = javaLangObject?.declarations?.find {
it is IrFunction && it.name.asString() == "clone"
@@ -1502,7 +1532,7 @@ open class KotlinFileExtractor(
fun extractCall(c: IrCall, callable: Label<out DbCallable>, stmtExprParent: StmtExprParent) {
with("call", c) {
val target = tryReplaceAndroidSyntheticFunction(c.symbol.owner)
val target = tryReplaceSyntheticFunction(c.symbol.owner)
// The vast majority of types of call want an expr context, so make one available lazily:
val exprParent by lazy {
@@ -2566,10 +2596,7 @@ open class KotlinFileExtractor(
tw.writeCallableEnclosingExpr(id, callable)
tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt)
val vId = if (owner is IrValueParameter && owner.isExtensionReceiver())
useValueParameter(owner, useFunction(owner.parent as IrFunction))
else
useValueDeclaration(owner)
val vId = useValueDeclaration(owner)
if (vId != null) {
tw.writeVariableBinding(id, vId)
}
@@ -2925,7 +2952,7 @@ open class KotlinFileExtractor(
stmtIdx: Int
) {
val paramId = tw.getFreshIdLabel<DbParam>()
val paramTypeRes = extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, null, paramId, false)
val paramTypeRes = extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, paramId, false)
val assignmentStmtId = tw.getFreshIdLabel<DbExprstmt>()
tw.writeStmts_exprstmt(assignmentStmtId, ids.constructorBlock, stmtIdx, ids.constructor)
@@ -3206,7 +3233,7 @@ open class KotlinFileExtractor(
tw.writeExprsKotlinType(callId, callType.kotlinResult.id)
this.writeExpressionMetadataToTrapFile(callId, invokeLabels.methodId, retId)
tw.writeCallableBinding(callId as Label<out DbCaller>, getId)
tw.writeCallableBinding(callId, getId)
this.writeThisAccess(callId, invokeLabels.methodId, retId)
for ((pIdx, p) in invokeLabels.parameters.withIndex()) {
@@ -3561,7 +3588,7 @@ open class KotlinFileExtractor(
val parameters = parameterTypes.mapIndexed { idx, p ->
val paramId = tw.getFreshIdLabel<DbParam>()
val paramType = extractValueParameter(paramId, p, "a$idx", locId, methodId, idx, null, paramId, false)
val paramType = extractValueParameter(paramId, p, "a$idx", locId, methodId, idx, paramId, false)
Pair(paramId, paramType)
}
@@ -3738,6 +3765,17 @@ open class KotlinFileExtractor(
}
}
/**
* Extracts a single wildcard type access expression with no enclosing callable and statement.
*/
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
val id = tw.getFreshIdLabel<DbWildcardtypeaccess>()
tw.writeExprs_wildcardtypeaccess(id, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
tw.writeHasLocation(id, location)
return id
}
/**
* Extracts a single type access expression with no enclosing callable and statement.
*/
@@ -3762,6 +3800,27 @@ open class KotlinFileExtractor(
return id
}
/**
* Extracts a type argument type access, introducing a wildcard type access if appropriate, or directly calling
* `extractTypeAccessRecursive` if the argument is invariant.
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
*/
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
val typeLabels by lazy { TypeResults(getTypeArgumentLabel(t), TypeResult(fakeKotlinType(), "TODO", "TODO")) }
when (t) {
is IrStarProjection -> extractWildcardTypeAccess(typeLabels, location, parent, idx)
is IrTypeProjection -> when(t.variance) {
Variance.INVARIANT -> extractTypeAccessRecursive(t.type, location, parent, idx, TypeContext.GENERIC_ARGUMENT)
else -> {
val wildcardLabel = extractWildcardTypeAccess(typeLabels, location, parent, idx)
// Mimic a Java extractor oddity, that it uses the child index to indicate what kind of wildcard this is
val boundChildIdx = if (t.variance == Variance.OUT_VARIANCE) 0 else 1
extractTypeAccessRecursive(t.type, location, wildcardLabel, boundChildIdx, TypeContext.GENERIC_ARGUMENT)
}
}
}
}
/**
* Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
@@ -3769,8 +3828,8 @@ open class KotlinFileExtractor(
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx)
if (t is IrSimpleType) {
t.arguments.filterIsInstance<IrType>().forEachIndexed { argIdx, arg ->
extractTypeAccessRecursive(arg, location, typeAccessId, argIdx, TypeContext.GENERIC_ARGUMENT)
t.arguments.forEachIndexed { argIdx, arg ->
extractWildcardTypeAccessRecursive(arg, location, typeAccessId, argIdx)
}
}
return typeAccessId
@@ -3997,17 +4056,14 @@ open class KotlinFileExtractor(
}
val typeOwner = e.typeOperandClassifier.owner
val samMember = if (typeOwner !is IrClass) {
if (typeOwner !is IrClass) {
logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e)
return
} else {
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
if (samMember == null) {
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
return
} else {
samMember
}
}
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
if (samMember == null) {
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
return
}
val javaResult = TypeResult(tw.getFreshIdLabel<DbClass>(), "", "")
@@ -4046,7 +4102,7 @@ open class KotlinFileExtractor(
// we would need to compose generic type substitutions -- for example, if we're implementing
// T UnaryOperator<T>.apply(T t) here, we would need to compose substitutions so we can implement
// the real underlying R Function<T, R>.apply(T t).
forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, idOverride = ids.function, locOverride = tw.getLocation(e))
forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, ids.function, tw.getLocation(e))
//body
val blockId = tw.getFreshIdLabel<DbBlock>()

View File

@@ -1,21 +1,28 @@
package com.github.codeql
import com.github.codeql.utils.*
import com.github.codeql.utils.versions.codeQlWithHasQuestionMark
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.ir.isFinalClass
import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
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.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
@@ -31,6 +38,17 @@ open class KotlinUsesExtractor(
val pluginContext: IrPluginContext,
val globalExtensionState: KotlinExtractorGlobalState
) {
val javaLangObject by lazy {
val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner
result?.let { extractExternalClassLater(it) }
result
}
val javaLangObjectType by lazy {
javaLangObject?.typeWith()
}
fun usePackage(pkg: String): Label<out DbPackage> {
return extractPackage(pkg)
}
@@ -48,62 +66,6 @@ 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
if (t is IrSimpleType && a.valueArgumentsCount == 1) {
val owner = t.classifier.owner
val v = a.getValueArgument(0)
if (owner is IrClass) {
val aPkg = owner.packageFqName?.asString()
val name = owner.name.asString()
if(aPkg == "kotlin.jvm" && name == "JvmName" && v is IrConst<*>) {
val value = v.value
if (value is String) {
return value
}
}
}
}
}
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
}
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
fun extractFileClass(f: IrFile): Label<out DbClass> {
val fileName = f.fileEntry.name
@@ -360,17 +322,17 @@ open class KotlinUsesExtractor(
} ?: c
}
fun tryReplaceAndroidSyntheticFunction(f: IrSimpleFunction): IrSimpleFunction {
private fun tryReplaceFunctionInSyntheticClass(f: IrFunction, getClassReplacement: (IrClass) -> IrClass): IrFunction {
val parentClass = f.parent as? IrClass ?: return f
val replacementClass = tryReplaceAndroidSyntheticClass(parentClass)
val replacementClass = getClassReplacement(parentClass)
if (replacementClass === parentClass)
return f
return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) {
val result = replacementClass.declarations.find { replacementDecl ->
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.zip(f.valueParameters).all {
it.first.type == it.second.type
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
erase(it.first.type) == erase(it.second.type)
}
} as IrSimpleFunction?
} as IrFunction?
if (result == null) {
logger.warn("Failed to replace synthetic class function ${f.name}")
} else {
@@ -380,6 +342,11 @@ open class KotlinUsesExtractor(
} ?: f
}
fun tryReplaceSyntheticFunction(f: IrFunction): IrFunction {
val androidReplacement = tryReplaceFunctionInSyntheticClass(f) { tryReplaceAndroidSyntheticClass(it) }
return tryReplaceFunctionInSyntheticClass(androidReplacement) { tryReplaceParcelizeRawType(it)?.first ?: it }
}
fun tryReplaceAndroidSyntheticField(f: IrField): IrField {
val parentClass = f.parent as? IrClass ?: return f
val replacementClass = tryReplaceAndroidSyntheticClass(parentClass)
@@ -398,42 +365,83 @@ open class KotlinUsesExtractor(
} ?: f
}
private fun tryReplaceType(cBeforeReplacement: IrClass, argsIncludingOuterClassesBeforeReplacement: List<IrTypeArgument>?): Pair<IrClass, List<IrTypeArgument>?> {
val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement)
val p = tryReplaceParcelizeRawType(c)
return Pair(
p?.first ?: c,
p?.second ?: argsIncludingOuterClassesBeforeReplacement
)
}
// `typeArgs` can be null to describe a raw generic type.
// For non-generic types it will be zero-length list.
fun addClassLabel(cBeforeReplacement: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, inReceiverContext: Boolean = false): TypeResult<DbClassorinterface> {
val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement)
val classLabelResult = getClassLabel(c, argsIncludingOuterClasses)
private fun addClassLabel(cBeforeReplacement: IrClass, argsIncludingOuterClassesBeforeReplacement: List<IrTypeArgument>?, inReceiverContext: Boolean = false): TypeResult<DbClassorinterface> {
val replaced = tryReplaceType(cBeforeReplacement, argsIncludingOuterClassesBeforeReplacement)
val replacedClass = replaced.first
val replacedArgsIncludingOuterClasses = replaced.second
val classLabelResult = getClassLabel(replacedClass, replacedArgsIncludingOuterClasses)
var instanceSeenBefore = true
val classLabel : Label<out DbClassorinterface> = tw.getLabelFor(classLabelResult.classLabel, {
val classLabel : Label<out DbClassorinterface> = tw.getLabelFor(classLabelResult.classLabel) {
instanceSeenBefore = false
extractClassLaterIfExternal(c)
})
extractClassLaterIfExternal(replacedClass)
}
if (argsIncludingOuterClasses == null || argsIncludingOuterClasses.isNotEmpty()) {
if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses.isNotEmpty()) {
// If this is a generic type instantiation or a raw type then it has no
// source entity, so we need to extract it here
val extractorWithCSource by lazy { this.withFileOfClass(c) }
val extractorWithCSource by lazy { this.withFileOfClass(replacedClass) }
if (!instanceSeenBefore) {
extractorWithCSource.extractClassInstance(c, argsIncludingOuterClasses)
extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses)
}
if (inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses)
extractorWithCSource.extractClassSupertypes(c, classLabel, supertypeMode, true)
extractorWithCSource.extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
val supertypeMode = if (replacedArgsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(replacedArgsIncludingOuterClasses)
extractorWithCSource.extractClassSupertypes(replacedClass, classLabel, supertypeMode, true)
extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses, classLabel)
}
}
return TypeResult(
classLabel,
c.fqNameWhenAvailable?.asString(),
replacedClass.fqNameWhenAvailable?.asString(),
classLabelResult.shortName)
}
private fun tryReplaceParcelizeRawType(c: IrClass): Pair<IrClass, List<IrTypeArgument>?>? {
if (c.superTypes.isNotEmpty() ||
c.origin != IrDeclarationOrigin.DEFINED ||
c.hasEqualFqName(FqName("java.lang.Object"))) {
return null
}
fun tryGetPair(arity: Int): Pair<IrClass, List<IrTypeArgument>?>? {
val replaced = pluginContext.referenceClass(c.fqNameWhenAvailable!!)?.owner ?: return null
return Pair(replaced, List(arity) { makeTypeProjection(pluginContext.irBuiltIns.anyNType, Variance.INVARIANT) })
}
// The list of types handled here match https://github.com/JetBrains/kotlin/blob/d7c7d1efd2c0983c13b175e9e4b1cda979521159/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ir/AndroidSymbols.kt
// Specifically, types are added for generic types created in AndroidSymbols.kt.
// This replacement is from a raw type to its matching parameterized type with `Object` type arguments.
return when (c.fqNameWhenAvailable?.asString()) {
"java.util.ArrayList" -> tryGetPair(1)
"java.util.LinkedHashMap" -> tryGetPair(2)
"java.util.LinkedHashSet" -> tryGetPair(1)
"java.util.List" -> tryGetPair(1)
"java.util.TreeMap" -> tryGetPair(2)
"java.util.TreeSet" -> tryGetPair(1)
"java.lang.Class" -> tryGetPair(1)
else -> null
}
}
fun useAnonymousClass(c: IrClass) =
tw.lm.anonymousTypeMapping.getOrPut(c) {
TypeResults(
@@ -702,7 +710,17 @@ open class KotlinUsesExtractor(
} else {
extractFileClass(dp)
}
is IrClass -> if (classTypeArguments != null && !dp.isAnonymousObject) useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id else useClassSource(dp)
is IrClass ->
if (classTypeArguments != null && !dp.isAnonymousObject) {
useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id
} else {
val replacedType = tryReplaceParcelizeRawType(dp)
if (replacedType == null) {
useClassSource(dp)
} else {
useClassInstance(replacedType.first, replacedType.second, inReceiverContext).typeResult.id
}
}
is IrFunction -> useFunction(dp)
is IrExternalPackageFragment -> {
// TODO
@@ -789,6 +807,110 @@ open class KotlinUsesExtractor(
else -> null
}
val javaUtilCollection by lazy {
val result = pluginContext.referenceClass(FqName("java.util.Collection"))?.owner
result?.let { extractExternalClassLater(it) }
result
}
val wildcardCollectionType by lazy {
javaUtilCollection?.let {
it.symbol.typeWithArguments(listOf(IrStarProjectionImpl))
}
}
private fun makeCovariant(t: IrTypeArgument) =
t.typeOrNull?.let { makeTypeProjection(it, Variance.OUT_VARIANCE) } ?: t
private fun makeArgumentsCovariant(t: IrType) = (t as? IrSimpleType)?.let {
t.toBuilder().also { b -> b.arguments = b.arguments.map(this::makeCovariant) }.buildSimpleType()
} ?: t
fun eraseCollectionsMethodParameterType(t: IrType, collectionsMethodName: String, paramIdx: Int) =
when(collectionsMethodName) {
"contains", "remove", "containsKey", "containsValue", "get", "indexOf", "lastIndexOf" -> javaLangObjectType
"getOrDefault" -> if (paramIdx == 0) javaLangObjectType else null
"containsAll", "removeAll", "retainAll" -> wildcardCollectionType
// Kotlin defines these like addAll(Collection<E>); Java uses addAll(Collection<? extends E>)
"putAll", "addAll" -> makeArgumentsCovariant(t)
else -> null
} ?: t
private fun overridesFunctionDefinedOn(f: IrFunction, packageName: String, className: String) =
(f as? IrSimpleFunction)?.let {
it.overriddenSymbols.any { overridden ->
overridden.owner.parentClassOrNull?.let { defnClass ->
defnClass.name.asString() == className &&
defnClass.packageFqName?.asString() == packageName
} ?: false
}
} ?: false
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun overridesCollectionsMethodWithAlteredParameterTypes(f: IrFunction) =
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(f.descriptor) != null ||
(f.name.asString() == "putAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableMap")) ||
(f.name.asString() == "addAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableCollection")) ||
(f.name.asString() == "addAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableList"))
private val jvmWildcardAnnotation = FqName("kotlin.jvm.JvmWildcard")
private val jvmWildcardSuppressionAnnotaton = FqName("kotlin.jvm.JvmSuppressWildcards")
private fun wildcardAdditionAllowed(v: Variance, t: IrType, addByDefault: Boolean) =
when {
t.hasAnnotation(jvmWildcardAnnotation) -> true
!addByDefault -> false
t.hasAnnotation(jvmWildcardSuppressionAnnotaton) -> false
v == Variance.IN_VARIANCE -> !(t.isNullableAny() || t.isAny())
v == Variance.OUT_VARIANCE -> ((t as? IrSimpleType)?.classOrNull?.owner?.isFinalClass) != true
else -> false
}
private fun addJavaLoweringArgumentWildcards(p: IrTypeParameter, t: IrTypeArgument, addByDefault: Boolean, javaType: JavaType?): IrTypeArgument =
(t as? IrTypeProjection)?.let {
val newBase = addJavaLoweringWildcards(it.type, addByDefault, javaType)
val newVariance =
if (it.variance == Variance.INVARIANT &&
p.variance != Variance.INVARIANT &&
// The next line forbids inferring a wildcard type when we have a corresponding Java type with conflicting variance.
// For example, Java might declare f(Comparable<CharSequence> cs), in which case we shouldn't add a `? super ...`
// wildcard. Note if javaType is unknown (e.g. this is a Kotlin source element), we assume wildcards should be added.
(javaType?.let { jt -> jt is JavaWildcardType && jt.isExtends == (p.variance == Variance.OUT_VARIANCE) } != false) &&
wildcardAdditionAllowed(p.variance, it.type, addByDefault))
p.variance
else
it.variance
if (newBase !== it.type || newVariance != it.variance)
makeTypeProjection(newBase, newVariance)
else
null
} ?: t
fun getJavaTypeArgument(jt: JavaType, idx: Int) =
when(jt) {
is JavaClassifierType -> jt.typeArguments.getOrNull(idx)
is JavaArrayType -> if (idx == 0) jt.componentType else null
else -> null
}
fun addJavaLoweringWildcards(t: IrType, addByDefault: Boolean, javaType: JavaType?): IrType =
(t as? IrSimpleType)?.let {
val typeParams = it.classOrNull?.owner?.typeParameters ?: return t
val newArgs = typeParams.zip(it.arguments).mapIndexed { idx, pair ->
addJavaLoweringArgumentWildcards(
pair.first,
pair.second,
addByDefault,
javaType?.let { jt -> getJavaTypeArgument(jt, idx) }
)
}
return if (newArgs.zip(it.arguments).all { pair -> pair.first === pair.second })
t
else
it.toBuilder().also { builder -> builder.arguments = newArgs }.buildSimpleType()
} ?: t
/*
* This is the normal getFunctionLabel function to use. If you want
* to refer to the function in its source class then
@@ -810,8 +932,21 @@ open class KotlinUsesExtractor(
* `java.lang.Throwable`, which isn't what we want. So we have to
* allow it to be passed in.
*/
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getFunctionLabel(f: IrFunction, maybeParentId: Label<out DbElement>?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) =
getFunctionLabel(f.parent, maybeParentId, getFunctionShortName(f).nameInDB, f.valueParameters, f.returnType, f.extensionReceiverParameter, getFunctionTypeParameters(f), classTypeArgsIncludingOuterClasses)
getFunctionLabel(
f.parent,
maybeParentId,
getFunctionShortName(f).nameInDB,
f.valueParameters,
getAdjustedReturnType(f),
f.extensionReceiverParameter,
getFunctionTypeParameters(f),
classTypeArgsIncludingOuterClasses,
overridesCollectionsMethodWithAlteredParameterTypes(f),
getJavaCallable(f),
!hasWildcardSuppressionAnnotation(f)
)
/*
* This function actually generates the label for a function.
@@ -837,6 +972,14 @@ open class KotlinUsesExtractor(
functionTypeParameters: List<IrTypeParameter>,
// The type arguments of enclosing classes of the function.
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?,
// If true, this method implements a Java Collections interface (Collection, Map or List) and may need
// parameter erasure to match the way this class will appear to an external consumer of the .class file.
overridesCollectionsMethod: Boolean,
// The Java signature of this callable, if known.
javaSignature: JavaMember?,
// If true, Java wildcards implied by Kotlin type parameter variance should be added by default to this function's value parameters' types.
// (Return-type wildcard addition is always off by default)
addParameterWildcardsByDefault: Boolean,
// The prefix used in the label. "callable", unless a property label is created, then it's "property".
prefix: String = "callable"
): String {
@@ -855,19 +998,28 @@ open class KotlinUsesExtractor(
enclosingClass?.let { notNullClass -> makeTypeGenericSubstitutionMap(notNullClass, notNullArgs) }
}
}
val getIdForFunctionLabel = { it: IrValueParameter ->
// Mimic the Java extractor's behaviour: functions with type parameters are named for their erased types;
val getIdForFunctionLabel = { it: IndexedValue<IrValueParameter> ->
// Kotlin rewrites certain Java collections types adding additional generic constraints-- for example,
// Collection.remove(Object) because Collection.remove(Collection::E) in the Kotlin universe.
// If this has happened, erase the type again to get the correct Java signature.
val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value.type, name, it.index) else it.value.type
// Add any wildcard types that the Kotlin compiler would add in the Java lowering of this function:
val withAddedWildcards = addJavaLoweringWildcards(maybeAmendedForCollections, addParameterWildcardsByDefault, javaSignature?.let { sig -> getJavaValueParameterType(sig, it.index) })
// Now substitute any class type parameters in:
val maybeSubbed = withAddedWildcards.substituteTypeAndArguments(substitutionMap, TypeContext.OTHER, pluginContext)
// Finally, mimic the Java extractor's behaviour by naming functions with type parameters for their erased types;
// those without type parameters are named for the generic type.
val maybeSubbed = it.type.substituteTypeAndArguments(substitutionMap, TypeContext.OTHER, pluginContext)
val maybeErased = if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed)
"{${useType(maybeErased).javaResult.id}}"
}
val paramTypeIds = allParams.joinToString(separator = ",", transform = getIdForFunctionLabel)
val paramTypeIds = allParams.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel)
val labelReturnType =
if (name == "<init>")
pluginContext.irBuiltIns.unitType
else
erase(returnType.substituteTypeAndArguments(substitutionMap, TypeContext.RETURN, pluginContext))
// Note that `addJavaLoweringWildcards` is not required here because the return type used to form the function
// label is always erased.
val returnTypeId = useType(labelReturnType, TypeContext.RETURN).javaResult.id
// This suffix is added to generic methods (and constructors) to match the Java extractor's behaviour.
// Comments in that extractor indicates it didn't want the label of the callable to clash with the raw
@@ -877,6 +1029,41 @@ open class KotlinUsesExtractor(
return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
}
fun getAdjustedReturnType(f: IrFunction) : IrType {
// The return type of `java.util.concurrent.ConcurrentHashMap<K,V>.keySet/0` is defined as `Set<K>` in the stubs inside the Android SDK.
// This does not match the Java SDK return type: `ConcurrentHashMap.KeySetView<K,V>`, so it's adjusted here.
// This is a deliberate change in the Android SDK: https://github.com/AndroidSDKSources/android-sdk-sources-for-api-level-31/blob/2c56b25f619575bea12f9c5520ed2259620084ac/java/util/concurrent/ConcurrentHashMap.java#L1244-L1249
// The annotation on the source is not visible in the android.jar, so we can't make the change based on that.
// TODO: there are other instances of `dalvik.annotation.codegen.CovariantReturnType` in the Android SDK, we should handle those too if they cause DB inconsistencies
val parentClass = f.parentClassOrNull
if (parentClass == null ||
parentClass.fqNameWhenAvailable?.asString() != "java.util.concurrent.ConcurrentHashMap" ||
getFunctionShortName(f).nameInDB != "keySet" ||
f.valueParameters.isNotEmpty() ||
f.returnType.classFqName?.asString() != "kotlin.collections.MutableSet") {
return f.returnType
}
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun getJavaCallable(f: IrFunction) = (f.descriptor.source as? JavaSourceElement)?.javaElement as? JavaMember
fun getJavaValueParameterType(m: JavaMember, idx: Int) = when(m) {
is JavaMethod -> m.valueParameters[idx].type
is JavaConstructor -> m.valueParameters[idx].type
else -> null
}
fun hasWildcardSuppressionAnnotation(d: IrDeclaration) =
d.hasAnnotation(jvmWildcardSuppressionAnnotaton) ||
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotaton) == true }
protected fun IrFunction.isLocalFunction(): Boolean {
return this.visibility == DescriptorVisibilities.LOCAL
}
@@ -1227,7 +1414,7 @@ open class KotlinUsesExtractor(
if (t.isArray() || t.isNullableArray()) {
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
val erasedElementType = erase(elementType)
return withQuestionMark((classifier as IrClassSymbol).typeWith(erasedElementType), t.hasQuestionMark)
return (classifier as IrClassSymbol).typeWith(erasedElementType).codeQlWithHasQuestionMark(t.hasQuestionMark)
}
if (owner is IrClass) {
@@ -1269,9 +1456,34 @@ open class KotlinUsesExtractor(
fun useValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>?): Label<out DbParam> =
tw.getLabelFor(getValueParameterLabel(vp, parent))
fun isDirectlyExposedCompanionObjectField(f: IrField) =
f.hasAnnotation(FqName("kotlin.jvm.JvmField")) ||
f.correspondingPropertySymbol?.owner?.let {
it.isConst || it.isLateinit
} ?: false
fun getFieldParent(f: IrField) =
f.parentClassOrNull?.let {
if (it.isCompanion && isDirectlyExposedCompanionObjectField(f))
it.parent
else
null
} ?: f.parent
// Gets a field's corresponding property's extension receiver type, if any
fun getExtensionReceiverType(f: IrField) =
f.correspondingPropertySymbol?.owner?.let {
(it.getter ?: it.setter)?.extensionReceiverParameter?.type
}
fun getFieldLabel(f: IrField): String {
val parentId = useDeclarationParent(f.parent, false)
return "@\"field;{$parentId};${f.name.asString()}\""
val parentId = useDeclarationParent(getFieldParent(f), false)
// Distinguish backing fields of properties based on their extension receiver type;
// otherwise two extension properties declared in the same enclosing context will get
// clashing trap labels. These are always private, so we can just make up a label without
// worrying about their names as seen from Java.
val extensionPropertyDiscriminator = getExtensionReceiverType(f)?.let { "extension;${useType(it)}" } ?: ""
return "@\"field;{$parentId};${extensionPropertyDiscriminator}${f.name.asString()}\""
}
fun useField(f: IrField): Label<out DbField> =
@@ -1299,7 +1511,7 @@ open class KotlinUsesExtractor(
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")
getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, javaSignature = null, addParameterWildcardsByDefault = false, prefix = "property")
}
}
@@ -1326,6 +1538,4 @@ open class KotlinUsesExtractor(
return tw.getVariableLabelFor<DbLocalvar>(v)
}
fun withQuestionMark(t: IrType, hasQuestionMark: Boolean) = if(hasQuestionMark) t.makeNullable() else t.makeNotNull()
}

View File

@@ -276,12 +276,6 @@ open class FileTrapWriter (
fun getLocation(e: IrElement): Label<DbLocation> {
return getLocation(e.startOffset, e.endOffset)
}
/**
* Gets a label for the location representing the whole of this file.
*/
fun getWholeFileLocation(): Label<DbLocation> {
return getWholeFileLocation(fileId)
}
/**
* Gets a label for the location corresponding to `startOffset` and
* `endOffset` within this file.
@@ -303,6 +297,12 @@ open class FileTrapWriter (
// to be 0.
return "file://$filePath"
}
/**
* Gets a label for the location representing the whole of this file.
*/
fun getWholeFileLocation(): Label<DbLocation> {
return getWholeFileLocation(fileId)
}
}
/**

View File

@@ -1,5 +1,6 @@
package com.github.codeql
import com.github.codeql.utils.getJvmName
import com.intellij.openapi.vfs.StandardFileSystems
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
@@ -18,17 +19,19 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
// and declarations within them into the parent class' JLS 13.1 name as
// specified above, followed by a `$` separator and then the short name
// for `that`.
private fun getName(d: IrDeclarationWithName) = (d as? IrAnnotationContainer)?.let { getJvmName(it) } ?: d.name.asString()
fun getIrDeclBinaryName(that: IrDeclaration): String {
val shortName = when(that) {
is IrDeclarationWithName -> that.name.asString()
is IrDeclarationWithName -> getName(that)
else -> "(unknown-name)"
}
val internalName = StringBuilder(shortName);
generateSequence(that.parent) { (it as? IrDeclaration)?.parent }
.forEach {
when (it) {
is IrClass -> internalName.insert(0, it.name.asString() + "$")
is IrPackageFragment -> it.fqName.asString().takeIf { it.isNotEmpty() }?.let { internalName.insert(0, "$it.") }
is IrClass -> internalName.insert(0, getName(it) + "$")
is IrPackageFragment -> it.fqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
}
}
return internalName.toString()

View File

@@ -0,0 +1,90 @@
package com.github.codeql.utils
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.packageFqName
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
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",
makeDescription(StandardNames.FqNames.mutableList, "removeAt") to "remove",
makeDescription(FqName("java.util.List"), "removeAt") to "remove",
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-ordinal>") to "ordinal",
makeDescription(FqName("java.lang.Enum"), "<get-ordinal>") to "ordinal",
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-name>") to "name",
makeDescription(FqName("java.lang.Enum"), "<get-name>") to "name",
makeDescription(StandardNames.FqNames.number.toSafe(), "toByte") to "byteValue",
makeDescription(FqName("java.lang.Number"), "toByte") to "byteValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toShort") to "shortValue",
makeDescription(FqName("java.lang.Number"), "toShort") to "shortValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toInt") to "intValue",
makeDescription(FqName("java.lang.Number"), "toInt") to "intValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toLong") to "longValue",
makeDescription(FqName("java.lang.Number"), "toLong") to "longValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toFloat") to "floatValue",
makeDescription(FqName("java.lang.Number"), "toFloat") to "floatValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toDouble") to "doubleValue",
makeDescription(FqName("java.lang.Number"), "toDouble") to "doubleValue",
)
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.parentClassOrNull?.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
if (t is IrSimpleType && a.valueArgumentsCount == 1) {
val owner = t.classifier.owner
val v = a.getValueArgument(0)
if (owner is IrClass) {
val aPkg = owner.packageFqName?.asString()
val name = owner.name.asString()
if(aPkg == "kotlin.jvm" && name == "JvmName" && v is IrConst<*>) {
val value = v.value
if (value is String) {
return value
}
}
}
}
}
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
}

View File

@@ -37,6 +37,30 @@ fun IrType.substituteTypeArguments(params: List<IrTypeParameter>, arguments: Lis
else -> this
}
fun IrSimpleType.substituteTypeArguments(substitutionMap: Map<IrTypeParameterSymbol, IrTypeArgument>): IrSimpleType {
if (substitutionMap.isEmpty()) return this
val newArguments = arguments.map {
if (it is IrTypeProjection) {
val itType = it.type
if (itType is IrSimpleType) {
subProjectedType(substitutionMap, itType, it.variance)
} else {
it
}
} else {
it
}
}
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
newArguments,
annotations
)
}
/**
* Returns true if substituting `innerVariance T` into the context `outerVariance []` discards all knowledge about
* what T could be.
@@ -76,30 +100,6 @@ private fun subProjectedType(substitutionMap: Map<IrTypeParameterSymbol, IrTypeA
}
} ?: makeTypeProjection(t.substituteTypeArguments(substitutionMap), outerVariance)
fun IrSimpleType.substituteTypeArguments(substitutionMap: Map<IrTypeParameterSymbol, IrTypeArgument>): IrSimpleType {
if (substitutionMap.isEmpty()) return this
val newArguments = arguments.map {
if (it is IrTypeProjection) {
val itType = it.type
if (itType is IrSimpleType) {
subProjectedType(substitutionMap, itType, it.variance)
} else {
it
}
} else {
it
}
}
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
newArguments,
annotations
)
}
fun IrTypeArgument.upperBound(context: IrPluginContext) =
when(this) {
is IrStarProjection -> context.irBuiltIns.anyNType

View File

@@ -92,6 +92,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.apache.IO
private import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.frameworks.Flexjson
private import semmle.code.java.frameworks.generated
private import semmle.code.java.frameworks.guava.Guava
private import semmle.code.java.frameworks.jackson.JacksonSerializability
private import semmle.code.java.frameworks.javaee.jsf.JSFRenderer

View File

@@ -242,8 +242,9 @@ Guard nullGuard(SsaVariable v, boolean branch, boolean isnull) {
}
/**
* A return statement that on a return value of `retval` allows the conclusion that the
* parameter `p` either is null or non-null as specified by `isnull`.
* A return statement in a non-overridable method that on a return value of
* `retval` allows the conclusion that the parameter `p` either is null or
* non-null as specified by `isnull`.
*/
private predicate validReturnInCustomNullGuard(
ReturnStmt ret, Parameter p, boolean retval, boolean isnull
@@ -251,7 +252,10 @@ private predicate validReturnInCustomNullGuard(
exists(Method m |
ret.getEnclosingCallable() = m and
p.getCallable() = m and
m.getReturnType().(PrimitiveType).hasName("boolean")
m.getReturnType().(PrimitiveType).hasName("boolean") and
not p.isVarargs() and
p.getType() instanceof RefType and
not m.isOverridable()
) and
exists(SsaImplicitInit ssa | ssa.isParameterDefinition(p) |
nullGuardedReturn(ret, ssa, isnull) and
@@ -267,6 +271,11 @@ private predicate nullGuardedReturn(ReturnStmt ret, SsaImplicitInit ssa, boolean
)
}
pragma[nomagic]
private Method returnStmtGetEnclosingCallable(ReturnStmt ret) {
ret.getEnclosingCallable() = result
}
/**
* Gets a non-overridable method with a boolean return value that performs a null-check
* on the `index`th parameter. A return value equal to `retval` allows us to conclude
@@ -274,14 +283,10 @@ private predicate nullGuardedReturn(ReturnStmt ret, SsaImplicitInit ssa, boolean
*/
private Method customNullGuard(int index, boolean retval, boolean isnull) {
exists(Parameter p |
result.getReturnType().(PrimitiveType).hasName("boolean") and
not result.isOverridable() and
p.getCallable() = result and
not p.isVarargs() and
p.getType() instanceof RefType and
p.getPosition() = index and
forex(ReturnStmt ret |
ret.getEnclosingCallable() = result and
returnStmtGetEnclosingCallable(ret) = result and
exists(Expr res | res = ret.getResult() |
not res.(BooleanLiteral).getBooleanValue() = retval.booleanNot()
)

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -3854,16 +3854,11 @@ class PathNode extends TPathNode {
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
private PathNode getASuccessorIfHidden() {
this.(PathNodeImpl).isHidden() and
result = this.(PathNodeImpl).getASuccessorImpl()
}
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() {
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
not this.(PathNodeImpl).isHidden() and
not result.(PathNodeImpl).isHidden()
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
reach(this) and
reach(result)
}
/** Holds if this node is a source. */
@@ -3871,7 +3866,18 @@ class PathNode extends TPathNode {
}
abstract private class PathNodeImpl extends PathNode {
abstract PathNode getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl();
private PathNodeImpl getASuccessorIfHidden() {
this.isHidden() and
result = this.getASuccessorImpl()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getASuccessorIfHidden*() and
not this.isHidden() and
not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3914,15 +3920,17 @@ abstract private class PathNodeImpl extends PathNode {
}
/** Holds if `n` can reach a sink. */
private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or directReach(n.getANonHiddenSuccessor())
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3931,7 +3939,7 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
@@ -4049,7 +4057,7 @@ private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override predicate isSource() { sourceNode(node, state, config) }
}
@@ -4365,8 +4373,8 @@ private module Subpaths {
}
pragma[nomagic]
private predicate hasSuccessor(PathNode pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessor() and
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getANonHiddenSuccessor() and
succNode = succ.getNodeEx()
}
@@ -4375,9 +4383,9 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
not ret.isHidden() and
@@ -4390,12 +4398,12 @@ private module Subpaths {
/**
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
predicate retReach(PathNodeImpl n) {
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
exists(PathNodeImpl mid |
retReach(mid) and
n.getASuccessor() = mid and
n.getANonHiddenSuccessor() = mid and
not subpaths(_, mid, _, _)
)
}

View File

@@ -304,6 +304,33 @@ class ContentSet instanceof Content {
}
}
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode() {
exists(Guard g, SsaVariable v, boolean branch, RValue use |
guardChecks(g, v.getAUse(), branch) and
use = v.getAUse() and
g.controls(use.getBasicBlock(), branch) and
result.asExpr() = use
)
}
}
/**
* A guard that validates some expression.
*

View File

@@ -1,16 +1,21 @@
/** Custom definitions related to the Apache Commons IO library. */
import java
import IOGenerated
private import semmle.code.java.dataflow.ExternalFlow
// TODO: manual models that were not generated yet
private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv {
/**
* Models that are not yet auto generated or where the generated summaries will
* be ignored.
* Note that if a callable has any handwritten summary, all generated summaries
* will be ignored for that callable.
*/
override predicate row(string row) {
row =
[
"org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0];Argument[2];taint",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0].Element;Argument[2];taint",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint",
"org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint",
"org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint",
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
/**
* A module importing all generated Models as Data models.
*/
import java
private module GeneratedFrameworks {
private import apache.IOGenerated
}

View File

@@ -141,26 +141,28 @@ private class StatePair extends TStatePair {
}
/**
* Holds for all constructed state pairs.
* Holds for `(fork, fork)` state pairs when `isFork(fork, _, _, _, _)` holds.
*
* Used in `statePairDist`
* Used in `statePairDistToFork`
*/
private predicate isStatePair(StatePair p) { any() }
private predicate isStatePairFork(StatePair p) {
exists(State fork | p = MkStatePair(fork, fork) and isFork(fork, _, _, _, _))
}
/**
* Holds if there are transitions from the components of `q` to the corresponding
* components of `r`.
*
* Used in `statePairDist`
* Used in `statePairDistToFork`
*/
private predicate delta2(StatePair q, StatePair r) { step(q, _, _, r) }
private predicate reverseStep(StatePair r, StatePair q) { step(q, _, _, r) }
/**
* Gets the minimum length of a path from `q` to `r` in the
* product automaton.
*/
private int statePairDist(StatePair q, StatePair r) =
shortestDistances(isStatePair/1, delta2/2)(q, r, result)
private int statePairDistToFork(StatePair q, StatePair r) =
shortestDistances(isStatePairFork/1, reverseStep/2)(r, q, result)
/**
* Holds if there are transitions from `q` to `r1` and from `q` to `r2`
@@ -255,14 +257,7 @@ private predicate step(StatePair q, InputSymbol s1, InputSymbol s2, State r1, St
private newtype TTrace =
Nil() or
Step(InputSymbol s1, InputSymbol s2, TTrace t) {
exists(StatePair p |
isReachableFromFork(_, p, t, _) and
step(p, s1, s2, _)
)
or
t = Nil() and isFork(_, s1, s2, _, _)
}
Step(InputSymbol s1, InputSymbol s2, TTrace t) { isReachableFromFork(_, _, s1, s2, t, _) }
/**
* A list of pairs of input symbols that describe a path in the product automaton
@@ -284,20 +279,28 @@ private class Trace extends TTrace {
* a path from `r` back to `(fork, fork)` with `rem` steps.
*/
private predicate isReachableFromFork(State fork, StatePair r, Trace w, int rem) {
exists(InputSymbol s1, InputSymbol s2, Trace v |
isReachableFromFork(fork, r, s1, s2, v, rem) and
w = Step(s1, s2, v)
)
}
private predicate isReachableFromFork(
State fork, StatePair r, InputSymbol s1, InputSymbol s2, Trace v, int rem
) {
// base case
exists(InputSymbol s1, InputSymbol s2, State q1, State q2 |
exists(State q1, State q2 |
isFork(fork, s1, s2, q1, q2) and
r = MkStatePair(q1, q2) and
w = Step(s1, s2, Nil()) and
rem = statePairDist(r, MkStatePair(fork, fork))
v = Nil() and
rem = statePairDistToFork(r, MkStatePair(fork, fork))
)
or
// recursive case
exists(StatePair p, Trace v, InputSymbol s1, InputSymbol s2 |
exists(StatePair p |
isReachableFromFork(fork, p, v, rem + 1) and
step(p, s1, s2, r) and
w = Step(s1, s2, v) and
rem >= statePairDist(r, MkStatePair(fork, fork))
rem = statePairDistToFork(r, MkStatePair(fork, fork))
)
}

View File

@@ -20,5 +20,5 @@ where
c.fromSource() and
exists(sc.getBody()) and
not exists(CloneMethod ssc | sc.callsSuper(ssc))
select sc, "This clone method does not call super.clone(), but is " + "overridden and called $@.",
c, "in a subclass"
select sc, "This clone method does not call super.clone(), but is overridden and called $@.", c,
"in a subclass"

View File

@@ -17,4 +17,4 @@ from Method m
where
m.hasName(m.getDeclaringType().getName()) and
m.fromSource()
select m, "This method has the same name as its declaring class." + " Should it be a constructor?"
select m, "This method has the same name as its declaring class. Should it be a constructor?"

View File

@@ -96,5 +96,4 @@ where
not exceptions(c, f) and
reason = nonSerialReason(f.getType())
select f,
"This field is in a serializable class, " + " but is not serializable itself because " + reason +
"."
"This field is in a serializable class, but is not serializable itself because " + reason + "."

View File

@@ -19,15 +19,13 @@ import semmle.code.java.security.PathCreation
import DataFlow::PathGraph
import TaintedPathCommon
class ContainsDotDotSanitizer extends DataFlow::BarrierGuard {
ContainsDotDotSanitizer() {
this.(MethodAccess).getMethod().hasName("contains") and
this.(MethodAccess).getAnArgument().(StringLiteral).getValue() = ".."
}
override predicate checks(Expr e, boolean branch) {
e = this.(MethodAccess).getQualifier() and branch = false
}
predicate containsDotDotSanitizer(Guard g, Expr e, boolean branch) {
exists(MethodAccess contains | g = contains |
contains.getMethod().hasName("contains") and
contains.getAnArgument().(StringLiteral).getValue() = ".." and
e = contains.getQualifier() and
branch = false
)
}
class TaintedPathConfig extends TaintTracking::Configuration {
@@ -41,10 +39,8 @@ class TaintedPathConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) {
exists(Type t | t = node.getType() | t instanceof BoxedType or t instanceof PrimitiveType)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof ContainsDotDotSanitizer
or
node = DataFlow::BarrierGuard<containsDotDotSanitizer/3>::getABarrierNode()
}
}

View File

@@ -1,7 +1,9 @@
/**
* @name Capture sink models.
* @description Finds public methods that act as sinks as they flow into a a known sink.
* @description Finds public methods that act as sinks as they flow into a known sink.
* @kind diagnostic
* @id java/utils/model-generator/sink-models
* @tags model-generator
*/
private import internal.CaptureModels

View File

@@ -1,7 +1,9 @@
/**
* @name Capture source models.
* @description Finds APIs that act as sources as they expose already known sources.
* @id java/utils/model-generator/sink-models
* @kind diagnostic
* @id java/utils/model-generator/source-models
* @tags model-generator
*/
private import internal.CaptureModels

View File

@@ -1,7 +1,9 @@
/**
* @name Capture summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id java/utils/model-generator/summary-models
* @tags model-generator
*/
private import internal.CaptureModels

View File

@@ -39,8 +39,9 @@ def regenerateModel(lgtmSlug, extractedDb):
modelFile = defaultModelPath + "/" + lgtmSlugToModelFile[lgtmSlug]
codeQlRoot = findGitRoot()
targetModel = codeQlRoot + "/" + modelFile
subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py", extractedDb,
targetModel])
subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py",
"--with-summaries", "--with-sinks",
extractedDb, targetModel])
print("Regenerated " + targetModel)
shutil.rmtree(tmpDir)

View File

@@ -232,4 +232,8 @@ string asInputArgument(DataFlow::Node source) {
* Holds if `kind` is a relevant sink kind for creating sink models.
*/
bindingset[kind]
predicate isRelevantSinkKind(string kind) { not kind = "logging" }
predicate isRelevantSinkKind(string kind) {
not kind = "logging" and
not kind.matches("regex-use%") and
not kind = "write-file"
}

View File

@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
/**
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
* must not be a digit), optionally followed by `=` and the expected value.
* more comma-separated tags optionally followed by `=` and the expected value.
*
* Tags must be only letters, digits, `-` and `_` (note that the first character
* must not be a digit), but can contain anything enclosed in a single set of
* square brackets.
*
* Examples:
* - `tag`
* - `tag=value`
* - `tag,tag2=value`
* - `tag[foo bar]=value`
*
* Not allowed:
* - `tag[[[foo bar]`
*/
private string expectationPattern() {
exists(string tag, string tags, string value |
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
// For example, `b"foo"`.

View File

@@ -0,0 +1,4 @@
| test.kt:4:5:6:5 | keySet | 0 | java.util.concurrent.ConcurrentHashMap$KeySetView<K,V> |
| test.kt:8:5:10:5 | keySet | 1 | java.util.concurrent.ConcurrentHashMap$KeySetView<K,V> |
| test.kt:17:5:19:5 | keySet | 0 | java.util.Set<K> |
| test.kt:21:5:23:5 | keySet | 1 | java.util.concurrent.OtherConcurrentHashMap$KeySetView<K,V> |

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.fromSource()
select m, m.getNumberOfParameters(), m.getReturnType().(RefType).getQualifiedName()

View File

@@ -0,0 +1,27 @@
package java.util.concurrent
class ConcurrentHashMap<K,V> {
fun keySet(): MutableSet<K> {
return null!!
}
fun keySet(p: V): KeySetView<K,V>? {
return null
}
class KeySetView<K,V> {
}
}
class OtherConcurrentHashMap<K,V> {
fun keySet(): MutableSet<K> {
return null!!
}
fun keySet(p: V): KeySetView<K,V>? {
return null
}
class KeySetView<K,V> {
}
}

View File

@@ -0,0 +1,9 @@
| |
| <clinit> |
| A |
| B |
| get |
| getX |
| invoke |
| x$delegatepackagename$$subpackagename$$A |
| x$delegatepackagename$$subpackagename$$B |

View File

@@ -0,0 +1,7 @@
package packagename.subpackagename
public class A { }
public class B { }
val A.x : String by lazy { "HelloA" }
val B.x : String by lazy { "HelloB" }

View File

@@ -0,0 +1,5 @@
import java
from Class c
where c.fromSource()
select c.getAMember().toString()

View File

@@ -0,0 +1 @@
fun usesEnum(e: Enum<*>) = e.ordinal.toString() + e.name

View File

@@ -0,0 +1,27 @@
| addAll |
| addRange |
| allOf |
| asIterator |
| clone |
| compareTo |
| complement |
| complementOf |
| copyOf |
| describeConstable |
| equals |
| finalize |
| getDeclaringClass |
| hasMoreElements |
| hashCode |
| name |
| nextElement |
| noneOf |
| of |
| ordinal |
| range |
| resolveConstantDesc |
| toString |
| typeCheck |
| usesEnum |
| valueOf |
| writeReplace |

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.getDeclaringType().getName().matches("Enum%")
select m.getName()

View File

@@ -31,7 +31,7 @@ delegatedProperties.kt:
# 87| 0: [MethodAccess] getValue(...)
# 87| -2: [TypeAccess] Integer
# 87| -1: [TypeAccess] PropertyReferenceDelegatesKt
# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegate
# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass
# 87| -1: [TypeAccess] DelegatedPropertiesKt
# 1| 1: [ExtensionReceiverAccess] this
# 87| 2: [PropertyRefExpr] ...::...
@@ -80,7 +80,7 @@ delegatedProperties.kt:
# 87| 0: [MethodAccess] setValue(...)
# 87| -2: [TypeAccess] Integer
# 87| -1: [TypeAccess] PropertyReferenceDelegatesKt
# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegate
# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass
# 87| -1: [TypeAccess] DelegatedPropertiesKt
# 1| 1: [ExtensionReceiverAccess] this
# 87| 2: [PropertyRefExpr] ...::...
@@ -118,7 +118,7 @@ delegatedProperties.kt:
# 87| 0: [TypeAccess] MyClass
# 87| 1: [TypeAccess] Integer
# 87| 3: [VarAccess] <set-?>
# 87| 5: [FieldDeclaration] KMutableProperty0<Integer> extDelegated$delegate;
# 87| 5: [FieldDeclaration] KMutableProperty0<Integer> extDelegated$delegateMyClass;
# 87| -1: [TypeAccess] KMutableProperty0<Integer>
# 87| 0: [TypeAccess] Integer
# 87| 0: [PropertyRefExpr] ...::...
@@ -237,9 +237,10 @@ delegatedProperties.kt:
# 18| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 18| 0: [Parameter] map
# 18| 0: [TypeAccess] Map<String,Object>
# 18| 0: [TypeAccess] Map<String,? extends Object>
# 18| 0: [TypeAccess] String
# 18| 1: [TypeAccess] Object
# 18| 1: [WildcardTypeAccess] ? ...
# 18| 0: [TypeAccess] Object
# 18| 5: [BlockStmt] { ... }
# 19| 0: [BlockStmt] { ... }
# 19| 0: [LocalVariableDeclStmt] var ...;
@@ -425,6 +426,7 @@ delegatedProperties.kt:
# 27| 0: [TypeAccess] Object
# 27| 1: [Parameter] property
# 27| 0: [TypeAccess] KProperty<?>
# 27| 0: [WildcardTypeAccess] ? ...
# 27| 5: [BlockStmt] { ... }
# 27| 0: [ReturnStmt] return ...
# 27| 0: [MethodAccess] getCurValue(...)
@@ -436,6 +438,7 @@ delegatedProperties.kt:
# 28| 0: [TypeAccess] Object
# 28| 1: [Parameter] property
# 28| 0: [TypeAccess] KProperty<?>
# 28| 0: [WildcardTypeAccess] ? ...
# 28| 2: [Parameter] value
# 28| 0: [TypeAccess] int
# 28| 5: [BlockStmt] { ... }
@@ -734,6 +737,7 @@ delegatedProperties.kt:
# 46| 0: [TypeAccess] Owner
# 46| 1: [Parameter] property
# 46| 0: [TypeAccess] KProperty<?>
# 46| 0: [WildcardTypeAccess] ? ...
# 46| 5: [BlockStmt] { ... }
# 47| 0: [ReturnStmt] return ...
# 47| 0: [IntegerLiteral] 1
@@ -744,6 +748,7 @@ delegatedProperties.kt:
# 49| 0: [TypeAccess] Owner
# 49| 1: [Parameter] property
# 49| 0: [TypeAccess] KProperty<?>
# 49| 0: [WildcardTypeAccess] ? ...
# 49| 2: [Parameter] value
# 49| 0: [TypeAccess] Integer
# 49| 5: [BlockStmt] { ... }
@@ -759,6 +764,7 @@ delegatedProperties.kt:
# 54| 0: [TypeAccess] Owner
# 54| 1: [Parameter] prop
# 54| 0: [TypeAccess] KProperty<?>
# 54| 0: [WildcardTypeAccess] ? ...
# 54| 5: [BlockStmt] { ... }
# 56| 0: [ReturnStmt] return ...
# 56| 0: [ClassInstanceExpr] new ResourceDelegate(...)
@@ -2051,44 +2057,44 @@ exprs.kt:
# 39| 27: [LocalVariableDeclStmt] var ...;
# 39| 1: [LocalVariableDeclExpr] by6
# 39| 0: [ValueEQExpr] ... (value equals) ...
# 39| 0: [MethodAccess] toInt(...)
# 39| 0: [MethodAccess] intValue(...)
# 39| -1: [VarAccess] byx
# 39| 1: [MethodAccess] toInt(...)
# 39| 1: [MethodAccess] intValue(...)
# 39| -1: [VarAccess] byy
# 40| 28: [LocalVariableDeclStmt] var ...;
# 40| 1: [LocalVariableDeclExpr] by7
# 40| 0: [ValueNEExpr] ... (value not-equals) ...
# 40| 0: [MethodAccess] toInt(...)
# 40| 0: [MethodAccess] intValue(...)
# 40| -1: [VarAccess] byx
# 40| 1: [MethodAccess] toInt(...)
# 40| 1: [MethodAccess] intValue(...)
# 40| -1: [VarAccess] byy
# 41| 29: [LocalVariableDeclStmt] var ...;
# 41| 1: [LocalVariableDeclExpr] by8
# 41| 0: [LTExpr] ... < ...
# 41| 0: [MethodAccess] toInt(...)
# 41| 0: [MethodAccess] intValue(...)
# 41| -1: [VarAccess] byx
# 41| 1: [MethodAccess] toInt(...)
# 41| 1: [MethodAccess] intValue(...)
# 41| -1: [VarAccess] byy
# 42| 30: [LocalVariableDeclStmt] var ...;
# 42| 1: [LocalVariableDeclExpr] by9
# 42| 0: [LEExpr] ... <= ...
# 42| 0: [MethodAccess] toInt(...)
# 42| 0: [MethodAccess] intValue(...)
# 42| -1: [VarAccess] byx
# 42| 1: [MethodAccess] toInt(...)
# 42| 1: [MethodAccess] intValue(...)
# 42| -1: [VarAccess] byy
# 43| 31: [LocalVariableDeclStmt] var ...;
# 43| 1: [LocalVariableDeclExpr] by10
# 43| 0: [GTExpr] ... > ...
# 43| 0: [MethodAccess] toInt(...)
# 43| 0: [MethodAccess] intValue(...)
# 43| -1: [VarAccess] byx
# 43| 1: [MethodAccess] toInt(...)
# 43| 1: [MethodAccess] intValue(...)
# 43| -1: [VarAccess] byy
# 44| 32: [LocalVariableDeclStmt] var ...;
# 44| 1: [LocalVariableDeclExpr] by11
# 44| 0: [GEExpr] ... >= ...
# 44| 0: [MethodAccess] toInt(...)
# 44| 0: [MethodAccess] intValue(...)
# 44| -1: [VarAccess] byx
# 44| 1: [MethodAccess] toInt(...)
# 44| 1: [MethodAccess] intValue(...)
# 44| -1: [VarAccess] byy
# 45| 33: [LocalVariableDeclStmt] var ...;
# 45| 1: [LocalVariableDeclExpr] by12
@@ -2126,44 +2132,44 @@ exprs.kt:
# 53| 40: [LocalVariableDeclStmt] var ...;
# 53| 1: [LocalVariableDeclExpr] s6
# 53| 0: [ValueEQExpr] ... (value equals) ...
# 53| 0: [MethodAccess] toInt(...)
# 53| 0: [MethodAccess] intValue(...)
# 53| -1: [VarAccess] sx
# 53| 1: [MethodAccess] toInt(...)
# 53| 1: [MethodAccess] intValue(...)
# 53| -1: [VarAccess] sy
# 54| 41: [LocalVariableDeclStmt] var ...;
# 54| 1: [LocalVariableDeclExpr] s7
# 54| 0: [ValueNEExpr] ... (value not-equals) ...
# 54| 0: [MethodAccess] toInt(...)
# 54| 0: [MethodAccess] intValue(...)
# 54| -1: [VarAccess] sx
# 54| 1: [MethodAccess] toInt(...)
# 54| 1: [MethodAccess] intValue(...)
# 54| -1: [VarAccess] sy
# 55| 42: [LocalVariableDeclStmt] var ...;
# 55| 1: [LocalVariableDeclExpr] s8
# 55| 0: [LTExpr] ... < ...
# 55| 0: [MethodAccess] toInt(...)
# 55| 0: [MethodAccess] intValue(...)
# 55| -1: [VarAccess] sx
# 55| 1: [MethodAccess] toInt(...)
# 55| 1: [MethodAccess] intValue(...)
# 55| -1: [VarAccess] sy
# 56| 43: [LocalVariableDeclStmt] var ...;
# 56| 1: [LocalVariableDeclExpr] s9
# 56| 0: [LEExpr] ... <= ...
# 56| 0: [MethodAccess] toInt(...)
# 56| 0: [MethodAccess] intValue(...)
# 56| -1: [VarAccess] sx
# 56| 1: [MethodAccess] toInt(...)
# 56| 1: [MethodAccess] intValue(...)
# 56| -1: [VarAccess] sy
# 57| 44: [LocalVariableDeclStmt] var ...;
# 57| 1: [LocalVariableDeclExpr] s10
# 57| 0: [GTExpr] ... > ...
# 57| 0: [MethodAccess] toInt(...)
# 57| 0: [MethodAccess] intValue(...)
# 57| -1: [VarAccess] sx
# 57| 1: [MethodAccess] toInt(...)
# 57| 1: [MethodAccess] intValue(...)
# 57| -1: [VarAccess] sy
# 58| 45: [LocalVariableDeclStmt] var ...;
# 58| 1: [LocalVariableDeclExpr] s11
# 58| 0: [GEExpr] ... >= ...
# 58| 0: [MethodAccess] toInt(...)
# 58| 0: [MethodAccess] intValue(...)
# 58| -1: [VarAccess] sx
# 58| 1: [MethodAccess] toInt(...)
# 58| 1: [MethodAccess] intValue(...)
# 58| -1: [VarAccess] sy
# 59| 46: [LocalVariableDeclStmt] var ...;
# 59| 1: [LocalVariableDeclExpr] s12
@@ -3081,8 +3087,9 @@ funcExprs.kt:
# 2| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 2| 0: [Parameter] f
# 2| 0: [TypeAccess] Function0<Object>
# 2| 0: [TypeAccess] Object
# 2| 0: [TypeAccess] Function0<? extends Object>
# 2| 0: [WildcardTypeAccess] ? ...
# 2| 0: [TypeAccess] Object
# 2| 5: [BlockStmt] { ... }
# 2| 0: [ExprStmt] <Expr>;
# 2| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
@@ -3093,8 +3100,9 @@ funcExprs.kt:
# 3| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 3| 0: [Parameter] f
# 3| 0: [TypeAccess] Function0<Object>
# 3| 0: [TypeAccess] Object
# 3| 0: [TypeAccess] Function0<? extends Object>
# 3| 0: [WildcardTypeAccess] ? ...
# 3| 0: [TypeAccess] Object
# 3| 5: [BlockStmt] { ... }
# 3| 0: [ExprStmt] <Expr>;
# 3| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
@@ -3107,8 +3115,9 @@ funcExprs.kt:
# 4| 0: [Parameter] x
# 4| 0: [TypeAccess] int
# 4| 1: [Parameter] f
# 4| 0: [TypeAccess] Function1<Integer,Integer>
# 4| 0: [TypeAccess] Integer
# 4| 0: [TypeAccess] Function1<? super Integer,Integer>
# 4| 0: [WildcardTypeAccess] ? ...
# 4| 1: [TypeAccess] Integer
# 4| 1: [TypeAccess] Integer
# 4| 5: [BlockStmt] { ... }
# 4| 0: [ExprStmt] <Expr>;
@@ -3123,9 +3132,10 @@ funcExprs.kt:
# 5| 0: [Parameter] x
# 5| 0: [TypeAccess] int
# 5| 1: [Parameter] f
# 5| 0: [TypeAccess] Function1<Object,Object>
# 5| 0: [TypeAccess] Function1<Object,? extends Object>
# 5| 0: [TypeAccess] Object
# 5| 1: [TypeAccess] Object
# 5| 1: [WildcardTypeAccess] ? ...
# 5| 0: [TypeAccess] Object
# 5| 5: [BlockStmt] { ... }
# 5| 0: [ExprStmt] <Expr>;
# 5| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
@@ -3139,9 +3149,11 @@ funcExprs.kt:
# 6| 0: [Parameter] x
# 6| 0: [TypeAccess] int
# 6| 1: [Parameter] f
# 6| 0: [TypeAccess] Function2<FuncRef,Integer,Integer>
# 6| 0: [TypeAccess] FuncRef
# 6| 1: [TypeAccess] Integer
# 6| 0: [TypeAccess] Function2<? super FuncRef,? super Integer,Integer>
# 6| 0: [WildcardTypeAccess] ? ...
# 6| 1: [TypeAccess] FuncRef
# 6| 1: [WildcardTypeAccess] ? ...
# 6| 1: [TypeAccess] Integer
# 6| 2: [TypeAccess] Integer
# 6| 5: [BlockStmt] { ... }
# 6| 0: [ExprStmt] <Expr>;
@@ -3158,9 +3170,11 @@ funcExprs.kt:
# 7| 0: [Parameter] x
# 7| 0: [TypeAccess] int
# 7| 1: [Parameter] f
# 7| 0: [TypeAccess] Function2<Integer,Integer,Integer>
# 7| 0: [TypeAccess] Integer
# 7| 1: [TypeAccess] Integer
# 7| 0: [TypeAccess] Function2<? super Integer,? super Integer,Integer>
# 7| 0: [WildcardTypeAccess] ? ...
# 7| 1: [TypeAccess] Integer
# 7| 1: [WildcardTypeAccess] ? ...
# 7| 1: [TypeAccess] Integer
# 7| 2: [TypeAccess] Integer
# 7| 5: [BlockStmt] { ... }
# 7| 0: [ExprStmt] <Expr>;
@@ -3176,9 +3190,11 @@ funcExprs.kt:
# 8| 0: [Parameter] x
# 8| 0: [TypeAccess] int
# 8| 1: [Parameter] f
# 8| 0: [TypeAccess] Function2<Integer,Integer,Integer>
# 8| 0: [TypeAccess] Integer
# 8| 1: [TypeAccess] Integer
# 8| 0: [TypeAccess] Function2<? super Integer,? super Integer,Integer>
# 8| 0: [WildcardTypeAccess] ? ...
# 8| 1: [TypeAccess] Integer
# 8| 1: [WildcardTypeAccess] ? ...
# 8| 1: [TypeAccess] Integer
# 8| 2: [TypeAccess] Integer
# 8| 5: [BlockStmt] { ... }
# 8| 0: [ExprStmt] <Expr>;
@@ -3194,11 +3210,14 @@ funcExprs.kt:
# 9| 0: [Parameter] x
# 9| 0: [TypeAccess] int
# 9| 1: [Parameter] f
# 9| 0: [TypeAccess] Function1<Integer,Function1<Integer,Double>>
# 9| 0: [TypeAccess] Integer
# 9| 1: [TypeAccess] Function1<Integer,Double>
# 9| 0: [TypeAccess] Integer
# 9| 1: [TypeAccess] Double
# 9| 0: [TypeAccess] Function1<? super Integer,? extends Function1<? super Integer,Double>>
# 9| 0: [WildcardTypeAccess] ? ...
# 9| 1: [TypeAccess] Integer
# 9| 1: [WildcardTypeAccess] ? ...
# 9| 0: [TypeAccess] Function1<? super Integer,Double>
# 9| 0: [WildcardTypeAccess] ? ...
# 9| 1: [TypeAccess] Integer
# 9| 1: [TypeAccess] Double
# 9| 5: [BlockStmt] { ... }
# 9| 0: [ExprStmt] <Expr>;
# 9| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
@@ -3214,29 +3233,51 @@ funcExprs.kt:
# 11| 0: [Parameter] x
# 11| 0: [TypeAccess] int
# 11| 1: [Parameter] f
# 11| 0: [TypeAccess] Function22<Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Unit>
# 11| 0: [TypeAccess] Integer
# 11| 1: [TypeAccess] Integer
# 11| 2: [TypeAccess] Integer
# 11| 3: [TypeAccess] Integer
# 11| 4: [TypeAccess] Integer
# 11| 5: [TypeAccess] Integer
# 11| 6: [TypeAccess] Integer
# 11| 7: [TypeAccess] Integer
# 11| 8: [TypeAccess] Integer
# 11| 9: [TypeAccess] Integer
# 11| 10: [TypeAccess] Integer
# 11| 11: [TypeAccess] Integer
# 11| 12: [TypeAccess] Integer
# 11| 13: [TypeAccess] Integer
# 11| 14: [TypeAccess] Integer
# 11| 15: [TypeAccess] Integer
# 11| 16: [TypeAccess] Integer
# 11| 17: [TypeAccess] Integer
# 11| 18: [TypeAccess] Integer
# 11| 19: [TypeAccess] Integer
# 11| 20: [TypeAccess] Integer
# 11| 21: [TypeAccess] Integer
# 11| 0: [TypeAccess] Function22<? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,Unit>
# 11| 0: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 1: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 2: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 3: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 4: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 5: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 6: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 7: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 8: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 9: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 10: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 11: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 12: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 13: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 14: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 15: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 16: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 17: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 18: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 19: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 20: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 21: [WildcardTypeAccess] ? ...
# 11| 1: [TypeAccess] Integer
# 11| 22: [TypeAccess] Unit
# 11| 5: [BlockStmt] { ... }
# 12| 0: [ExprStmt] <Expr>;
@@ -3271,29 +3312,52 @@ funcExprs.kt:
# 14| 0: [TypeAccess] int
# 14| 1: [Parameter] f
# 14| 0: [TypeAccess] FunctionN<String>
# 14| 0: [TypeAccess] Integer
# 14| 1: [TypeAccess] Integer
# 14| 2: [TypeAccess] Integer
# 14| 3: [TypeAccess] Integer
# 14| 4: [TypeAccess] Integer
# 14| 5: [TypeAccess] Integer
# 14| 6: [TypeAccess] Integer
# 14| 7: [TypeAccess] Integer
# 14| 8: [TypeAccess] Integer
# 14| 9: [TypeAccess] Integer
# 14| 10: [TypeAccess] Integer
# 14| 11: [TypeAccess] Integer
# 14| 12: [TypeAccess] Integer
# 14| 13: [TypeAccess] Integer
# 14| 14: [TypeAccess] Integer
# 14| 15: [TypeAccess] Integer
# 14| 16: [TypeAccess] Integer
# 14| 17: [TypeAccess] Integer
# 14| 18: [TypeAccess] Integer
# 14| 19: [TypeAccess] Integer
# 14| 20: [TypeAccess] Integer
# 14| 21: [TypeAccess] Integer
# 14| 22: [TypeAccess] Integer
# 14| 0: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 1: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 2: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 3: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 4: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 5: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 6: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 7: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 8: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 9: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 10: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 11: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 12: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 13: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 14: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 15: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 16: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 17: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 18: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 19: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 20: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 21: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 22: [WildcardTypeAccess] ? ...
# 14| 1: [TypeAccess] Integer
# 14| 23: [TypeAccess] String
# 14| 5: [BlockStmt] { ... }
# 15| 0: [ExprStmt] <Expr>;
@@ -3335,30 +3399,54 @@ funcExprs.kt:
# 17| 0: [TypeAccess] int
# 17| 1: [Parameter] f
# 17| 0: [TypeAccess] FunctionN<String>
# 17| 0: [TypeAccess] FuncRef
# 17| 1: [TypeAccess] Integer
# 17| 2: [TypeAccess] Integer
# 17| 3: [TypeAccess] Integer
# 17| 4: [TypeAccess] Integer
# 17| 5: [TypeAccess] Integer
# 17| 6: [TypeAccess] Integer
# 17| 7: [TypeAccess] Integer
# 17| 8: [TypeAccess] Integer
# 17| 9: [TypeAccess] Integer
# 17| 10: [TypeAccess] Integer
# 17| 11: [TypeAccess] Integer
# 17| 12: [TypeAccess] Integer
# 17| 13: [TypeAccess] Integer
# 17| 14: [TypeAccess] Integer
# 17| 15: [TypeAccess] Integer
# 17| 16: [TypeAccess] Integer
# 17| 17: [TypeAccess] Integer
# 17| 18: [TypeAccess] Integer
# 17| 19: [TypeAccess] Integer
# 17| 20: [TypeAccess] Integer
# 17| 21: [TypeAccess] Integer
# 17| 22: [TypeAccess] Integer
# 17| 23: [TypeAccess] Integer
# 17| 0: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] FuncRef
# 17| 1: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 2: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 3: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 4: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 5: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 6: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 7: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 8: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 9: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 10: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 11: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 12: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 13: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 14: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 15: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 16: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 17: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 18: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 19: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 20: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 21: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 22: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 23: [WildcardTypeAccess] ? ...
# 17| 1: [TypeAccess] Integer
# 17| 24: [TypeAccess] String
# 17| 5: [BlockStmt] { ... }
# 18| 0: [ExprStmt] <Expr>;
@@ -4496,8 +4584,9 @@ funcExprs.kt:
# 58| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 58| 0: [Parameter] l
# 58| 0: [TypeAccess] Function0<T>
# 58| 0: [TypeAccess] T
# 58| 0: [TypeAccess] Function0<? extends T>
# 58| 0: [WildcardTypeAccess] ? ...
# 58| 0: [TypeAccess] T
# 58| 5: [BlockStmt] { ... }
# 59| 15: [ExtensionMethod] f3
# 59| 3: [TypeAccess] int
@@ -4685,10 +4774,11 @@ funcExprs.kt:
# 77| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 77| 0: [Parameter] f
# 77| 0: [TypeAccess] Function1<Generic<Generic<Integer>>,String>
# 77| 0: [TypeAccess] Generic<Generic<Integer>>
# 77| 0: [TypeAccess] Generic<Integer>
# 77| 0: [TypeAccess] Integer
# 77| 0: [TypeAccess] Function1<? super Generic<Generic<Integer>>,String>
# 77| 0: [WildcardTypeAccess] ? ...
# 77| 1: [TypeAccess] Generic<Generic<Integer>>
# 77| 0: [TypeAccess] Generic<Integer>
# 77| 0: [TypeAccess] Integer
# 77| 1: [TypeAccess] String
# 77| 5: [BlockStmt] { ... }
# 79| 6: [Class,GenericType,ParameterizedType] Generic

View File

@@ -14,24 +14,24 @@
| exprs.kt:36:15:36:23 | ... - ... | exprs.kt:36:15:36:17 | byx | exprs.kt:36:21:36:23 | byy |
| exprs.kt:37:15:37:23 | ... / ... | exprs.kt:37:15:37:17 | byx | exprs.kt:37:21:37:23 | byy |
| exprs.kt:38:15:38:23 | ... % ... | exprs.kt:38:15:38:17 | byx | exprs.kt:38:21:38:23 | byy |
| exprs.kt:39:15:39:24 | ... (value equals) ... | exprs.kt:39:15:39:17 | toInt(...) | exprs.kt:39:22:39:24 | toInt(...) |
| exprs.kt:40:15:40:24 | ... (value not-equals) ... | exprs.kt:40:15:40:17 | toInt(...) | exprs.kt:40:22:40:24 | toInt(...) |
| exprs.kt:41:15:41:23 | ... < ... | exprs.kt:41:15:41:17 | toInt(...) | exprs.kt:41:21:41:23 | toInt(...) |
| exprs.kt:42:15:42:24 | ... <= ... | exprs.kt:42:15:42:17 | toInt(...) | exprs.kt:42:22:42:24 | toInt(...) |
| exprs.kt:43:16:43:24 | ... > ... | exprs.kt:43:16:43:18 | toInt(...) | exprs.kt:43:22:43:24 | toInt(...) |
| exprs.kt:44:16:44:25 | ... >= ... | exprs.kt:44:16:44:18 | toInt(...) | exprs.kt:44:23:44:25 | toInt(...) |
| exprs.kt:39:15:39:24 | ... (value equals) ... | exprs.kt:39:15:39:17 | intValue(...) | exprs.kt:39:22:39:24 | intValue(...) |
| exprs.kt:40:15:40:24 | ... (value not-equals) ... | exprs.kt:40:15:40:17 | intValue(...) | exprs.kt:40:22:40:24 | intValue(...) |
| exprs.kt:41:15:41:23 | ... < ... | exprs.kt:41:15:41:17 | intValue(...) | exprs.kt:41:21:41:23 | intValue(...) |
| exprs.kt:42:15:42:24 | ... <= ... | exprs.kt:42:15:42:17 | intValue(...) | exprs.kt:42:22:42:24 | intValue(...) |
| exprs.kt:43:16:43:24 | ... > ... | exprs.kt:43:16:43:18 | intValue(...) | exprs.kt:43:22:43:24 | intValue(...) |
| exprs.kt:44:16:44:25 | ... >= ... | exprs.kt:44:16:44:18 | intValue(...) | exprs.kt:44:23:44:25 | intValue(...) |
| exprs.kt:45:16:45:26 | ... == ... | exprs.kt:45:16:45:18 | byx | exprs.kt:45:24:45:26 | byy |
| exprs.kt:46:16:46:26 | ... != ... | exprs.kt:46:16:46:18 | byx | exprs.kt:46:24:46:26 | byy |
| exprs.kt:49:14:49:20 | ... + ... | exprs.kt:49:14:49:15 | sx | exprs.kt:49:19:49:20 | sy |
| exprs.kt:50:14:50:20 | ... - ... | exprs.kt:50:14:50:15 | sx | exprs.kt:50:19:50:20 | sy |
| exprs.kt:51:14:51:20 | ... / ... | exprs.kt:51:14:51:15 | sx | exprs.kt:51:19:51:20 | sy |
| exprs.kt:52:14:52:20 | ... % ... | exprs.kt:52:14:52:15 | sx | exprs.kt:52:19:52:20 | sy |
| exprs.kt:53:14:53:21 | ... (value equals) ... | exprs.kt:53:14:53:15 | toInt(...) | exprs.kt:53:20:53:21 | toInt(...) |
| exprs.kt:54:14:54:21 | ... (value not-equals) ... | exprs.kt:54:14:54:15 | toInt(...) | exprs.kt:54:20:54:21 | toInt(...) |
| exprs.kt:55:14:55:20 | ... < ... | exprs.kt:55:14:55:15 | toInt(...) | exprs.kt:55:19:55:20 | toInt(...) |
| exprs.kt:56:14:56:21 | ... <= ... | exprs.kt:56:14:56:15 | toInt(...) | exprs.kt:56:20:56:21 | toInt(...) |
| exprs.kt:57:15:57:21 | ... > ... | exprs.kt:57:15:57:16 | toInt(...) | exprs.kt:57:20:57:21 | toInt(...) |
| exprs.kt:58:15:58:22 | ... >= ... | exprs.kt:58:15:58:16 | toInt(...) | exprs.kt:58:21:58:22 | toInt(...) |
| exprs.kt:53:14:53:21 | ... (value equals) ... | exprs.kt:53:14:53:15 | intValue(...) | exprs.kt:53:20:53:21 | intValue(...) |
| exprs.kt:54:14:54:21 | ... (value not-equals) ... | exprs.kt:54:14:54:15 | intValue(...) | exprs.kt:54:20:54:21 | intValue(...) |
| exprs.kt:55:14:55:20 | ... < ... | exprs.kt:55:14:55:15 | intValue(...) | exprs.kt:55:19:55:20 | intValue(...) |
| exprs.kt:56:14:56:21 | ... <= ... | exprs.kt:56:14:56:15 | intValue(...) | exprs.kt:56:20:56:21 | intValue(...) |
| exprs.kt:57:15:57:21 | ... > ... | exprs.kt:57:15:57:16 | intValue(...) | exprs.kt:57:20:57:21 | intValue(...) |
| exprs.kt:58:15:58:22 | ... >= ... | exprs.kt:58:15:58:16 | intValue(...) | exprs.kt:58:21:58:22 | intValue(...) |
| exprs.kt:59:15:59:23 | ... == ... | exprs.kt:59:15:59:16 | sx | exprs.kt:59:22:59:23 | sy |
| exprs.kt:60:15:60:23 | ... != ... | exprs.kt:60:15:60:16 | sx | exprs.kt:60:22:60:23 | sy |
| exprs.kt:63:14:63:20 | ... + ... | exprs.kt:63:14:63:15 | lx | exprs.kt:63:19:63:20 | ly |

View File

@@ -16,7 +16,7 @@ delegatedProperties
| delegatedProperties.kt:77:5:77:49 | delegatedToTopLevel | delegatedToTopLevel | non-local | delegatedProperties.kt:77:34:77:49 | delegatedToTopLevel$delegate | delegatedProperties.kt:77:37:77:49 | ...::... |
| delegatedProperties.kt:79:5:79:38 | max | max | non-local | delegatedProperties.kt:79:18:79:38 | max$delegate | delegatedProperties.kt:79:21:79:38 | ...::... |
| delegatedProperties.kt:82:9:82:54 | delegatedToMember3 | delegatedToMember3 | local | delegatedProperties.kt:82:37:82:54 | KMutableProperty0<Integer> delegatedToMember3$delegate | delegatedProperties.kt:82:40:82:54 | ...::... |
| delegatedProperties.kt:87:1:87:46 | extDelegated | extDelegated | non-local | delegatedProperties.kt:87:31:87:46 | extDelegated$delegate | delegatedProperties.kt:87:34:87:46 | ...::... |
| delegatedProperties.kt:87:1:87:46 | extDelegated | extDelegated | non-local | delegatedProperties.kt:87:31:87:46 | extDelegated$delegateMyClass | delegatedProperties.kt:87:34:87:46 | ...::... |
delegatedPropertyTypes
| delegatedProperties.kt:6:9:9:9 | prop1 | file://:0:0:0:0 | int | file://<external>/Lazy.class:0:0:0:0 | Lazy<Integer> |
| delegatedProperties.kt:19:9:19:51 | varResource1 | file://:0:0:0:0 | int | delegatedProperties.kt:45:1:51:1 | ResourceDelegate |

View File

@@ -64,7 +64,8 @@
| delegatedProperties.kt:11:17:11:21 | Object | delegatedProperties.kt:5:5:12:5 | fn | TypeAccess |
| delegatedProperties.kt:11:17:11:21 | new (...) | delegatedProperties.kt:5:5:12:5 | fn | ClassInstanceExpr |
| delegatedProperties.kt:18:5:40:5 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:18:12:18:33 | Map<String,Object> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:18:12:18:33 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:18:12:18:33 | Map<String,? extends Object> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:18:12:18:33 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:18:12:18:33 | String | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:19:31:19:51 | ...::... | delegatedProperties.kt:19:31:19:51 | <get-varResource1> | PropertyRefExpr |
@@ -148,11 +149,13 @@
| delegatedProperties.kt:26:28:26:28 | 0 | delegatedProperties.kt:25:64:31:9 | | IntegerLiteral |
| delegatedProperties.kt:27:22:27:88 | int | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:27:35:27:47 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:27:50:27:71 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:27:50:27:71 | KProperty<?> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:27:81:27:88 | getCurValue(...) | delegatedProperties.kt:27:22:27:88 | getValue | MethodAccess |
| delegatedProperties.kt:27:81:27:88 | this | delegatedProperties.kt:27:22:27:88 | getValue | ThisAccess |
| delegatedProperties.kt:28:22:30:13 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:28:35:28:47 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:28:50:28:71 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:28:50:28:71 | KProperty<?> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:28:74:28:83 | int | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:29:17:29:24 | setCurValue(...) | delegatedProperties.kt:28:22:30:13 | setValue | MethodAccess |
@@ -280,14 +283,17 @@
| delegatedProperties.kt:42:30:42:47 | setValue(...) | delegatedProperties.kt:42:27:42:47 | setVarResource0 | MethodAccess |
| delegatedProperties.kt:46:14:48:5 | int | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:46:27:46:41 | Owner | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:46:44:46:65 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:46:44:46:65 | KProperty<?> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:47:16:47:16 | 1 | delegatedProperties.kt:46:14:48:5 | getValue | IntegerLiteral |
| delegatedProperties.kt:49:14:50:5 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:49:27:49:41 | Owner | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:49:44:49:65 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:49:44:49:65 | KProperty<?> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:49:68:49:78 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:54:14:57:5 | ResourceDelegate | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:54:34:54:48 | Owner | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:54:51:54:68 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| delegatedProperties.kt:54:51:54:68 | KProperty<?> | file://:0:0:0:0 | <none> | TypeAccess |
| delegatedProperties.kt:56:16:56:33 | ResourceDelegate | delegatedProperties.kt:54:14:57:5 | provideDelegate | TypeAccess |
| delegatedProperties.kt:56:16:56:33 | new ResourceDelegate(...) | delegatedProperties.kt:54:14:57:5 | provideDelegate | ClassInstanceExpr |
@@ -830,9 +836,9 @@
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | set | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | set | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | setExtDelegated | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:0:0:0:0 | <clinit> | VarAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:87:31:87:46 | getExtDelegated | VarAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:87:31:87:46 | setExtDelegated | VarAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:0:0:0:0 | <clinit> | VarAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:31:87:46 | getExtDelegated | VarAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:31:87:46 | setExtDelegated | VarAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | delegatedProperties.kt:87:31:87:46 | getExtDelegated | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | delegatedProperties.kt:87:31:87:46 | setExtDelegated | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1008,40 +1014,40 @@
| exprs.kt:38:21:38:23 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:39:5:39:24 | by6 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:39:15:39:17 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:39:15:39:17 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:39:15:39:17 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:39:15:39:24 | ... (value equals) ... | exprs.kt:4:1:136:1 | topLevelMethod | ValueEQExpr |
| exprs.kt:39:22:39:24 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:39:22:39:24 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:39:22:39:24 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:40:5:40:24 | by7 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:40:15:40:17 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:40:15:40:17 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:40:15:40:17 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:40:15:40:24 | ... (value not-equals) ... | exprs.kt:4:1:136:1 | topLevelMethod | ValueNEExpr |
| exprs.kt:40:22:40:24 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:40:22:40:24 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:40:22:40:24 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:41:5:41:23 | by8 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:41:15:41:17 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:41:15:41:17 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:41:15:41:17 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:41:15:41:23 | ... < ... | exprs.kt:4:1:136:1 | topLevelMethod | LTExpr |
| exprs.kt:41:21:41:23 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:41:21:41:23 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:41:21:41:23 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:42:5:42:24 | by9 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:42:15:42:17 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:42:15:42:17 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:42:15:42:17 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:42:15:42:24 | ... <= ... | exprs.kt:4:1:136:1 | topLevelMethod | LEExpr |
| exprs.kt:42:22:42:24 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:42:22:42:24 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:42:22:42:24 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:43:5:43:24 | by10 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:43:16:43:18 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:43:16:43:18 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:43:16:43:18 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:43:16:43:24 | ... > ... | exprs.kt:4:1:136:1 | topLevelMethod | GTExpr |
| exprs.kt:43:22:43:24 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:43:22:43:24 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:43:22:43:24 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:44:5:44:25 | by11 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:44:16:44:18 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:44:16:44:18 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:44:16:44:18 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:44:16:44:25 | ... >= ... | exprs.kt:4:1:136:1 | topLevelMethod | GEExpr |
| exprs.kt:44:23:44:25 | byy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:44:23:44:25 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:44:23:44:25 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:45:5:45:26 | by12 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:45:16:45:18 | byx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:45:16:45:26 | ... == ... | exprs.kt:4:1:136:1 | topLevelMethod | EQExpr |
@@ -1069,41 +1075,41 @@
| exprs.kt:52:14:52:20 | ... % ... | exprs.kt:4:1:136:1 | topLevelMethod | RemExpr |
| exprs.kt:52:19:52:20 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:53:5:53:21 | s6 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:53:14:53:15 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:53:14:53:15 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:53:14:53:15 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:53:14:53:21 | ... (value equals) ... | exprs.kt:4:1:136:1 | topLevelMethod | ValueEQExpr |
| exprs.kt:53:20:53:21 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:53:20:53:21 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:53:20:53:21 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:54:5:54:21 | s7 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:54:14:54:15 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:54:14:54:15 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:54:14:54:15 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:54:14:54:21 | ... (value not-equals) ... | exprs.kt:4:1:136:1 | topLevelMethod | ValueNEExpr |
| exprs.kt:54:20:54:21 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:54:20:54:21 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:54:20:54:21 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:55:5:55:20 | s8 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:55:14:55:15 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:55:14:55:15 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:55:14:55:15 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:55:14:55:20 | ... < ... | exprs.kt:4:1:136:1 | topLevelMethod | LTExpr |
| exprs.kt:55:19:55:20 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:55:19:55:20 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:55:19:55:20 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:56:5:56:21 | s9 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:56:14:56:15 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:56:14:56:15 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:56:14:56:15 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:56:14:56:21 | ... <= ... | exprs.kt:4:1:136:1 | topLevelMethod | LEExpr |
| exprs.kt:56:20:56:21 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:56:20:56:21 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:56:20:56:21 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:57:5:57:21 | s10 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:57:15:57:16 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:57:15:57:16 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:57:15:57:16 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:57:15:57:21 | ... > ... | exprs.kt:4:1:136:1 | topLevelMethod | GTExpr |
| exprs.kt:57:20:57:21 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:57:20:57:21 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:57:20:57:21 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:58:5:58:22 | s11 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:58:15:58:16 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:58:15:58:16 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:58:15:58:16 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:58:15:58:22 | ... >= ... | exprs.kt:4:1:136:1 | topLevelMethod | GEExpr |
| exprs.kt:58:21:58:22 | intValue(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:58:21:58:22 | sy | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:58:21:58:22 | toInt(...) | exprs.kt:4:1:136:1 | topLevelMethod | MethodAccess |
| exprs.kt:59:5:59:23 | s12 | exprs.kt:4:1:136:1 | topLevelMethod | LocalVariableDeclExpr |
| exprs.kt:59:15:59:16 | sx | exprs.kt:4:1:136:1 | topLevelMethod | VarAccess |
| exprs.kt:59:15:59:23 | ... == ... | exprs.kt:4:1:136:1 | topLevelMethod | EQExpr |
@@ -1725,14 +1731,16 @@
| funcExprs.kt:1:42:1:44 | Unit | funcExprs.kt:1:1:1:46 | functionExpression0a | TypeAccess |
| funcExprs.kt:1:42:1:44 | invoke(...) | funcExprs.kt:1:1:1:46 | functionExpression0a | MethodAccess |
| funcExprs.kt:2:1:2:47 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:2:26:2:38 | Function0<Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:2:26:2:38 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:2:26:2:38 | Function0<? extends Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:2:26:2:38 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:2:43:2:43 | f | funcExprs.kt:2:1:2:47 | functionExpression0b | VarAccess |
| funcExprs.kt:2:43:2:45 | <implicit coercion to unit> | funcExprs.kt:2:1:2:47 | functionExpression0b | ImplicitCoercionToUnitExpr |
| funcExprs.kt:2:43:2:45 | Unit | funcExprs.kt:2:1:2:47 | functionExpression0b | TypeAccess |
| funcExprs.kt:2:43:2:45 | invoke(...) | funcExprs.kt:2:1:2:47 | functionExpression0b | MethodAccess |
| funcExprs.kt:3:1:3:46 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:3:26:3:37 | Function0<Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:3:26:3:37 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:3:26:3:37 | Function0<? extends Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:3:26:3:37 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:3:42:3:42 | f | funcExprs.kt:3:1:3:46 | functionExpression0c | VarAccess |
| funcExprs.kt:3:42:3:44 | <implicit coercion to unit> | funcExprs.kt:3:1:3:46 | functionExpression0c | ImplicitCoercionToUnitExpr |
@@ -1740,7 +1748,8 @@
| funcExprs.kt:3:42:3:44 | invoke(...) | funcExprs.kt:3:1:3:46 | functionExpression0c | MethodAccess |
| funcExprs.kt:4:1:4:58 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:26:4:31 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:34:4:48 | Function1<Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:34:4:48 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:4:34:4:48 | Function1<? super Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:34:4:48 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:34:4:48 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:4:53:4:53 | f | funcExprs.kt:4:1:4:58 | functionExpression1a | VarAccess |
@@ -1750,7 +1759,8 @@
| funcExprs.kt:4:55:4:55 | x | funcExprs.kt:4:1:4:58 | functionExpression1a | VarAccess |
| funcExprs.kt:5:1:5:60 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:26:5:31 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:34:5:50 | Function1<Object,Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:34:5:50 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:5:34:5:50 | Function1<Object,? extends Object> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:34:5:50 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:34:5:50 | Object | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:5:55:5:55 | f | funcExprs.kt:5:1:5:60 | functionExpression1b | VarAccess |
@@ -1760,8 +1770,10 @@
| funcExprs.kt:5:57:5:57 | x | funcExprs.kt:5:1:5:60 | functionExpression1b | VarAccess |
| funcExprs.kt:6:1:6:78 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:26:6:31 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:34:6:57 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:6:34:6:57 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:6:34:6:57 | FuncRef | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:34:6:57 | Function2<FuncRef,Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:34:6:57 | Function2<? super FuncRef,? super Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:34:6:57 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:34:6:57 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:6:62:6:62 | f | funcExprs.kt:6:1:6:78 | functionExpression1c | VarAccess |
@@ -1773,7 +1785,9 @@
| funcExprs.kt:6:75:6:75 | x | funcExprs.kt:6:1:6:78 | functionExpression1c | VarAccess |
| funcExprs.kt:7:1:7:65 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:25:7:30 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:33:7:52 | Function2<Integer,Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:33:7:52 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:7:33:7:52 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:7:33:7:52 | Function2<? super Integer,? super Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:33:7:52 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:33:7:52 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:7:33:7:52 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1785,7 +1799,9 @@
| funcExprs.kt:7:62:7:62 | x | funcExprs.kt:7:1:7:65 | functionExpression2 | VarAccess |
| funcExprs.kt:8:1:8:63 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:25:8:30 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:33:8:51 | Function2<Integer,Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:33:8:51 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:8:33:8:51 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:8:33:8:51 | Function2<? super Integer,? super Integer,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:33:8:51 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:33:8:51 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:8:33:8:51 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1797,9 +1813,12 @@
| funcExprs.kt:8:60:8:60 | x | funcExprs.kt:8:1:8:63 | functionExpression3 | VarAccess |
| funcExprs.kt:9:1:9:74 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:25:9:30 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:9:33:9:61 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:9:33:9:61 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:9:33:9:61 | Double | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Function1<Integer,Double> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Function1<Integer,Function1<Integer,Double>> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Function1<? super Integer,? extends Function1<? super Integer,Double>> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Function1<? super Integer,Double> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:33:9:61 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:9:66:9:66 | f | funcExprs.kt:9:1:9:74 | functionExpression4 | VarAccess |
@@ -1811,7 +1830,29 @@
| funcExprs.kt:9:71:9:71 | x | funcExprs.kt:9:1:9:74 | functionExpression4 | VarAccess |
| funcExprs.kt:11:1:13:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:26:11:31 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:34:11:154 | Function22<Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Unit> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:11:34:11:154 | Function22<? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,? super Integer,Unit> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:34:11:154 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:34:11:154 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:11:34:11:154 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1861,6 +1902,29 @@
| funcExprs.kt:12:49:12:49 | x | funcExprs.kt:11:1:13:1 | functionExpression22 | VarAccess |
| funcExprs.kt:14:1:16:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:14:26:14:31 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:14:34:14:161 | FunctionN<String> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:14:34:14:161 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:14:34:14:161 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -1919,6 +1983,30 @@
| funcExprs.kt:15:51:15:51 | x | funcExprs.kt:14:1:16:1 | functionExpression23 | VarAccess |
| funcExprs.kt:17:1:19:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:17:27:17:32 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:17:35:17:171 | FuncRef | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:17:35:17:171 | FunctionN<String> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:17:35:17:171 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
@@ -2733,7 +2821,8 @@
| funcExprs.kt:55:34:55:39 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:55:49:55:49 | 5 | funcExprs.kt:55:23:55:49 | invoke | IntegerLiteral |
| funcExprs.kt:58:1:58:25 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:58:12:58:21 | Function0<T> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:58:12:58:21 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:58:12:58:21 | Function0<? extends T> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:58:12:58:21 | T | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:59:1:59:22 | int | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:59:5:59:7 | int | file://:0:0:0:0 | <none> | TypeAccess |
@@ -2809,7 +2898,8 @@
| funcExprs.kt:75:14:75:14 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:75:20:75:20 | a | funcExprs.kt:75:12:75:22 | invoke | StringLiteral |
| funcExprs.kt:77:13:77:60 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:77:20:77:55 | Function1<Generic<Generic<Integer>>,String> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:77:20:77:55 | ? ... | file://:0:0:0:0 | <none> | WildcardTypeAccess |
| funcExprs.kt:77:20:77:55 | Function1<? super Generic<Generic<Integer>>,String> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:77:20:77:55 | Generic<Generic<Integer>> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:77:20:77:55 | Generic<Integer> | file://:0:0:0:0 | <none> | TypeAccess |
| funcExprs.kt:77:20:77:55 | Integer | file://:0:0:0:0 | <none> | TypeAccess |

View File

@@ -1,3 +1,3 @@
| test.kt:4:5:4:138 | f1 | FunctionN<String> | String |
| test.kt:5:5:5:134 | f2 | FunctionN<T1> | T1 |
| test.kt:6:5:6:110 | f3 | FunctionN<T3> | T3 |
| test.kt:5:5:5:134 | f2 | FunctionN<? extends T1> | ? extends T1 |
| test.kt:6:5:6:110 | f3 | FunctionN<? extends T3> | ? extends T3 |

View File

@@ -0,0 +1,28 @@
import java.util.Map;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.AbstractCollection;
import java.util.List;
import java.util.AbstractList;
public class Test {
public static void test(
Map<String, String> p1,
AbstractMap<String, String> p2,
Collection<String> p3,
AbstractCollection<String> p4,
List<String> p5,
AbstractList<String> p6) {
// Use a method of each to ensure method prototypes are extracted:
p1.remove("Hello");
p2.remove("Hello");
p3.remove("Hello");
p4.remove("Hello");
p5.remove("Hello");
p6.remove("Hello");
}
}

View File

@@ -0,0 +1,411 @@
methodWithDuplicate
#select
| AbstractCollection | add | E |
| AbstractCollection | addAll | Collection<? extends E> |
| AbstractCollection | contains | Object |
| AbstractCollection | containsAll | Collection<?> |
| AbstractCollection | remove | Object |
| AbstractCollection | removeAll | Collection<?> |
| AbstractCollection | retainAll | Collection<?> |
| AbstractCollection | toArray | T[] |
| AbstractCollection<E> | add | E |
| AbstractCollection<E> | addAll | Collection<? extends E> |
| AbstractCollection<E> | contains | Object |
| AbstractCollection<E> | containsAll | Collection<?> |
| AbstractCollection<E> | remove | Object |
| AbstractCollection<E> | removeAll | Collection<?> |
| AbstractCollection<E> | retainAll | Collection<?> |
| AbstractCollection<E> | toArray | T[] |
| AbstractCollection<String> | add | String |
| AbstractCollection<String> | addAll | Collection<? extends String> |
| AbstractCollection<String> | contains | Object |
| AbstractCollection<String> | containsAll | Collection<?> |
| AbstractCollection<String> | remove | Object |
| AbstractCollection<String> | removeAll | Collection<?> |
| AbstractCollection<String> | retainAll | Collection<?> |
| AbstractCollection<String> | toArray | T[] |
| AbstractList | add | E |
| AbstractList | add | int |
| AbstractList | addAll | Collection<? extends E> |
| AbstractList | addAll | int |
| AbstractList | equals | Object |
| AbstractList | get | int |
| AbstractList | indexOf | Object |
| AbstractList | lastIndexOf | Object |
| AbstractList | listIterator | int |
| AbstractList | remove | int |
| AbstractList | removeRange | int |
| AbstractList | set | E |
| AbstractList | set | int |
| AbstractList | subList | int |
| AbstractList | subListRangeCheck | int |
| AbstractList<E> | add | E |
| AbstractList<E> | add | int |
| AbstractList<E> | addAll | Collection<? extends E> |
| AbstractList<E> | addAll | int |
| AbstractList<E> | equals | Object |
| AbstractList<E> | get | int |
| AbstractList<E> | indexOf | Object |
| AbstractList<E> | lastIndexOf | Object |
| AbstractList<E> | listIterator | int |
| AbstractList<E> | remove | int |
| AbstractList<E> | removeRange | int |
| AbstractList<E> | set | E |
| AbstractList<E> | set | int |
| AbstractList<E> | subList | int |
| AbstractList<E> | subListRangeCheck | int |
| AbstractMap | containsEntry | Entry<?,?> |
| AbstractMap | containsKey | Object |
| AbstractMap | containsValue | Object |
| AbstractMap | equals | Object |
| AbstractMap | get | Object |
| AbstractMap | put | K |
| AbstractMap | put | V |
| AbstractMap | putAll | Map<? extends K,? extends V> |
| AbstractMap | remove | Object |
| AbstractMap<Identity,Entry<?>> | containsKey | Object |
| AbstractMap<Identity,Entry<?>> | containsValue | Object |
| AbstractMap<Identity,Entry<?>> | equals | Object |
| AbstractMap<Identity,Entry<?>> | get | Object |
| AbstractMap<Identity,Entry<?>> | put | Entry<?> |
| AbstractMap<Identity,Entry<?>> | put | Identity |
| AbstractMap<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
| AbstractMap<Identity,Entry<?>> | remove | Object |
| AbstractMap<K,V> | containsKey | Object |
| AbstractMap<K,V> | containsValue | Object |
| AbstractMap<K,V> | equals | Object |
| AbstractMap<K,V> | get | Object |
| AbstractMap<K,V> | put | K |
| AbstractMap<K,V> | put | V |
| AbstractMap<K,V> | putAll | Map<? extends K,? extends V> |
| AbstractMap<K,V> | remove | Object |
| AbstractMap<String,String> | containsEntry | Entry<?,?> |
| AbstractMap<String,String> | containsKey | Object |
| AbstractMap<String,String> | containsValue | Object |
| AbstractMap<String,String> | equals | Object |
| AbstractMap<String,String> | get | Object |
| AbstractMap<String,String> | put | String |
| AbstractMap<String,String> | putAll | Map<? extends String,? extends String> |
| AbstractMap<String,String> | remove | Object |
| AbstractMutableCollection | add | E |
| AbstractMutableList | add | E |
| AbstractMutableList | add | int |
| AbstractMutableList | remove | int |
| AbstractMutableList | set | E |
| AbstractMutableList | set | int |
| AbstractMutableMap | put | K |
| AbstractMutableMap | put | V |
| Collection | add | E |
| Collection | addAll | Collection<? extends E> |
| Collection | contains | Object |
| Collection | containsAll | Collection<?> |
| Collection | equals | Object |
| Collection | remove | Object |
| Collection | removeAll | Collection<?> |
| Collection | removeIf | Predicate<? super E> |
| Collection | retainAll | Collection<?> |
| Collection | toArray | IntFunction<T[]> |
| Collection | toArray | T[] |
| Collection<E> | add | E |
| Collection<E> | addAll | Collection<? extends E> |
| Collection<E> | contains | Object |
| Collection<E> | containsAll | Collection<?> |
| Collection<E> | remove | Object |
| Collection<E> | removeAll | Collection<?> |
| Collection<E> | removeIf | Predicate<? super E> |
| Collection<E> | retainAll | Collection<?> |
| Collection<E> | toArray | IntFunction<T[]> |
| Collection<E> | toArray | T[] |
| Collection<Entry<K,V>> | add | Entry<K,V> |
| Collection<Entry<K,V>> | addAll | Collection<? extends Entry<K,V>> |
| Collection<Entry<K,V>> | contains | Object |
| Collection<Entry<K,V>> | containsAll | Collection<?> |
| Collection<Entry<K,V>> | remove | Object |
| Collection<Entry<K,V>> | removeAll | Collection<?> |
| Collection<Entry<K,V>> | removeIf | Predicate<? super Entry<K,V>> |
| Collection<Entry<K,V>> | retainAll | Collection<?> |
| Collection<Entry<K,V>> | toArray | IntFunction<T[]> |
| Collection<Entry<K,V>> | toArray | T[] |
| Collection<K> | add | K |
| Collection<K> | addAll | Collection<? extends K> |
| Collection<K> | contains | Object |
| Collection<K> | containsAll | Collection<?> |
| Collection<K> | remove | Object |
| Collection<K> | removeAll | Collection<?> |
| Collection<K> | removeIf | Predicate<? super K> |
| Collection<K> | retainAll | Collection<?> |
| Collection<K> | toArray | IntFunction<T[]> |
| Collection<K> | toArray | T[] |
| Collection<String> | add | String |
| Collection<String> | addAll | Collection<? extends String> |
| Collection<String> | contains | Object |
| Collection<String> | containsAll | Collection<?> |
| Collection<String> | equals | Object |
| Collection<String> | remove | Object |
| Collection<String> | removeAll | Collection<?> |
| Collection<String> | removeIf | Predicate<? super String> |
| Collection<String> | retainAll | Collection<?> |
| Collection<String> | toArray | IntFunction<T[]> |
| Collection<String> | toArray | T[] |
| Collection<V> | add | V |
| Collection<V> | addAll | Collection<? extends V> |
| Collection<V> | contains | Object |
| Collection<V> | containsAll | Collection<?> |
| Collection<V> | remove | Object |
| Collection<V> | removeAll | Collection<?> |
| Collection<V> | removeIf | Predicate<? super V> |
| Collection<V> | retainAll | Collection<?> |
| Collection<V> | toArray | IntFunction<T[]> |
| Collection<V> | toArray | T[] |
| List | add | E |
| List | add | int |
| List | addAll | Collection<? extends E> |
| List | addAll | int |
| List | contains | Object |
| List | containsAll | Collection<?> |
| List | copyOf | Collection<? extends E> |
| List | equals | Object |
| List | get | int |
| List | indexOf | Object |
| List | lastIndexOf | Object |
| List | listIterator | int |
| List | of | E |
| List | of | E[] |
| List | remove | Object |
| List | remove | int |
| List | removeAll | Collection<?> |
| List | replaceAll | UnaryOperator<E> |
| List | retainAll | Collection<?> |
| List | set | E |
| List | set | int |
| List | sort | Comparator<? super E> |
| List | subList | int |
| List | toArray | T[] |
| List<E> | add | E |
| List<E> | add | int |
| List<E> | addAll | Collection<? extends E> |
| List<E> | addAll | int |
| List<E> | contains | Object |
| List<E> | containsAll | Collection<?> |
| List<E> | copyOf | Collection<? extends E> |
| List<E> | get | int |
| List<E> | indexOf | Object |
| List<E> | lastIndexOf | Object |
| List<E> | listIterator | int |
| List<E> | of | E |
| List<E> | of | E[] |
| List<E> | remove | Object |
| List<E> | remove | int |
| List<E> | removeAll | Collection<?> |
| List<E> | replaceAll | UnaryOperator<E> |
| List<E> | retainAll | Collection<?> |
| List<E> | set | E |
| List<E> | set | int |
| List<E> | sort | Comparator<? super E> |
| List<E> | subList | int |
| List<E> | toArray | T[] |
| List<String> | add | String |
| List<String> | add | int |
| List<String> | addAll | Collection<? extends String> |
| List<String> | addAll | int |
| List<String> | contains | Object |
| List<String> | containsAll | Collection<?> |
| List<String> | copyOf | Collection<? extends E> |
| List<String> | equals | Object |
| List<String> | get | int |
| List<String> | indexOf | Object |
| List<String> | lastIndexOf | Object |
| List<String> | listIterator | int |
| List<String> | of | E |
| List<String> | of | E[] |
| List<String> | remove | Object |
| List<String> | remove | int |
| List<String> | removeAll | Collection<?> |
| List<String> | replaceAll | UnaryOperator<String> |
| List<String> | retainAll | Collection<?> |
| List<String> | set | String |
| List<String> | set | int |
| List<String> | sort | Comparator<? super String> |
| List<String> | subList | int |
| List<String> | toArray | T[] |
| Map | compute | BiFunction<? super K,? super V,? extends V> |
| Map | compute | K |
| Map | computeIfAbsent | Function<? super K,? extends V> |
| Map | computeIfAbsent | K |
| Map | computeIfPresent | BiFunction<? super K,? super V,? extends V> |
| Map | computeIfPresent | K |
| Map | containsKey | Object |
| Map | containsValue | Object |
| Map | copyOf | Map<? extends K,? extends V> |
| Map | entry | K |
| Map | entry | V |
| Map | equals | Object |
| Map | forEach | BiConsumer<? super K,? super V> |
| Map | get | Object |
| Map | getOrDefault | Object |
| Map | getOrDefault | V |
| Map | merge | BiFunction<? super V,? super V,? extends V> |
| Map | merge | K |
| Map | merge | V |
| Map | of | K |
| Map | of | V |
| Map | ofEntries | Entry<? extends K,? extends V>[] |
| Map | put | K |
| Map | put | V |
| Map | putAll | Map<? extends K,? extends V> |
| Map | putIfAbsent | K |
| Map | putIfAbsent | V |
| Map | remove | Object |
| Map | replace | K |
| Map | replace | V |
| Map | replaceAll | BiFunction<? super K,? super V,? extends V> |
| Map<Identity,Entry<?>> | compute | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
| Map<Identity,Entry<?>> | compute | Identity |
| Map<Identity,Entry<?>> | computeIfAbsent | Function<? super Identity,? extends Entry<?>> |
| Map<Identity,Entry<?>> | computeIfAbsent | Identity |
| Map<Identity,Entry<?>> | computeIfPresent | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
| Map<Identity,Entry<?>> | computeIfPresent | Identity |
| Map<Identity,Entry<?>> | containsKey | Object |
| Map<Identity,Entry<?>> | containsValue | Object |
| Map<Identity,Entry<?>> | copyOf | Map<? extends K,? extends V> |
| Map<Identity,Entry<?>> | entry | K |
| Map<Identity,Entry<?>> | entry | V |
| Map<Identity,Entry<?>> | forEach | BiConsumer<? super Identity,? super Entry<?>> |
| Map<Identity,Entry<?>> | get | Object |
| Map<Identity,Entry<?>> | getOrDefault | Entry<?> |
| Map<Identity,Entry<?>> | getOrDefault | Object |
| Map<Identity,Entry<?>> | merge | BiFunction<? super Entry<?>,? super Entry<?>,? extends Entry<?>> |
| Map<Identity,Entry<?>> | merge | Entry<?> |
| Map<Identity,Entry<?>> | merge | Identity |
| Map<Identity,Entry<?>> | of | K |
| Map<Identity,Entry<?>> | of | V |
| Map<Identity,Entry<?>> | ofEntries | Entry<? extends K,? extends V>[] |
| Map<Identity,Entry<?>> | put | Entry<?> |
| Map<Identity,Entry<?>> | put | Identity |
| Map<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
| Map<Identity,Entry<?>> | putIfAbsent | Entry<?> |
| Map<Identity,Entry<?>> | putIfAbsent | Identity |
| Map<Identity,Entry<?>> | remove | Object |
| Map<Identity,Entry<?>> | replace | Entry<?> |
| Map<Identity,Entry<?>> | replace | Identity |
| Map<Identity,Entry<?>> | replaceAll | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
| Map<K,V> | compute | BiFunction<? super K,? super V,? extends V> |
| Map<K,V> | compute | K |
| Map<K,V> | computeIfAbsent | Function<? super K,? extends V> |
| Map<K,V> | computeIfAbsent | K |
| Map<K,V> | computeIfPresent | BiFunction<? super K,? super V,? extends V> |
| Map<K,V> | computeIfPresent | K |
| Map<K,V> | containsKey | Object |
| Map<K,V> | containsValue | Object |
| Map<K,V> | copyOf | Map<? extends K,? extends V> |
| Map<K,V> | entry | K |
| Map<K,V> | entry | V |
| Map<K,V> | forEach | BiConsumer<? super K,? super V> |
| Map<K,V> | get | Object |
| Map<K,V> | getOrDefault | Object |
| Map<K,V> | getOrDefault | V |
| Map<K,V> | merge | BiFunction<? super V,? super V,? extends V> |
| Map<K,V> | merge | K |
| Map<K,V> | merge | V |
| Map<K,V> | of | K |
| Map<K,V> | of | V |
| Map<K,V> | ofEntries | Entry<? extends K,? extends V>[] |
| Map<K,V> | put | K |
| Map<K,V> | put | V |
| Map<K,V> | putAll | Map<? extends K,? extends V> |
| Map<K,V> | putIfAbsent | K |
| Map<K,V> | putIfAbsent | V |
| Map<K,V> | remove | Object |
| Map<K,V> | replace | K |
| Map<K,V> | replace | V |
| Map<K,V> | replaceAll | BiFunction<? super K,? super V,? extends V> |
| Map<Object,Object> | compute | BiFunction<? super Object,? super Object,? extends Object> |
| Map<Object,Object> | compute | Object |
| Map<Object,Object> | computeIfAbsent | Function<? super Object,? extends Object> |
| Map<Object,Object> | computeIfAbsent | Object |
| Map<Object,Object> | computeIfPresent | BiFunction<? super Object,? super Object,? extends Object> |
| Map<Object,Object> | computeIfPresent | Object |
| Map<Object,Object> | containsKey | Object |
| Map<Object,Object> | containsValue | Object |
| Map<Object,Object> | copyOf | Map<? extends K,? extends V> |
| Map<Object,Object> | entry | K |
| Map<Object,Object> | entry | V |
| Map<Object,Object> | forEach | BiConsumer<? super Object,? super Object> |
| Map<Object,Object> | get | Object |
| Map<Object,Object> | getOrDefault | Object |
| Map<Object,Object> | merge | BiFunction<? super Object,? super Object,? extends Object> |
| Map<Object,Object> | merge | Object |
| Map<Object,Object> | of | K |
| Map<Object,Object> | of | V |
| Map<Object,Object> | ofEntries | Entry<? extends K,? extends V>[] |
| Map<Object,Object> | put | Object |
| Map<Object,Object> | putAll | Map<? extends Object,? extends Object> |
| Map<Object,Object> | putIfAbsent | Object |
| Map<Object,Object> | remove | Object |
| Map<Object,Object> | replace | Object |
| Map<Object,Object> | replaceAll | BiFunction<? super Object,? super Object,? extends Object> |
| Map<String,String> | compute | BiFunction<? super String,? super String,? extends String> |
| Map<String,String> | compute | String |
| Map<String,String> | computeIfAbsent | Function<? super String,? extends String> |
| Map<String,String> | computeIfAbsent | String |
| Map<String,String> | computeIfPresent | BiFunction<? super String,? super String,? extends String> |
| Map<String,String> | computeIfPresent | String |
| Map<String,String> | containsKey | Object |
| Map<String,String> | containsValue | Object |
| Map<String,String> | copyOf | Map<? extends K,? extends V> |
| Map<String,String> | entry | K |
| Map<String,String> | entry | V |
| Map<String,String> | equals | Object |
| Map<String,String> | forEach | BiConsumer<? super String,? super String> |
| Map<String,String> | get | Object |
| Map<String,String> | getOrDefault | Object |
| Map<String,String> | getOrDefault | String |
| Map<String,String> | merge | BiFunction<? super String,? super String,? extends String> |
| Map<String,String> | merge | String |
| Map<String,String> | of | K |
| Map<String,String> | of | V |
| Map<String,String> | ofEntries | Entry<? extends K,? extends V>[] |
| Map<String,String> | put | String |
| Map<String,String> | putAll | Map<? extends String,? extends String> |
| Map<String,String> | putIfAbsent | String |
| Map<String,String> | remove | Object |
| Map<String,String> | replace | String |
| Map<String,String> | replaceAll | BiFunction<? super String,? super String,? extends String> |
| MutableCollection | add | E |
| MutableCollection | addAll | Collection<? extends E> |
| MutableCollection | remove | Object |
| MutableCollection | removeAll | Collection<?> |
| MutableCollection | removeIf | Predicate<? super E> |
| MutableCollection | retainAll | Collection<?> |
| MutableList | add | E |
| MutableList | add | int |
| MutableList | addAll | Collection<? extends E> |
| MutableList | addAll | int |
| MutableList | listIterator | int |
| MutableList | remove | Object |
| MutableList | remove | int |
| MutableList | removeAll | Collection<?> |
| MutableList | replaceAll | UnaryOperator<E> |
| MutableList | retainAll | Collection<?> |
| MutableList | set | E |
| MutableList | set | int |
| MutableList | sort | Comparator<? super E> |
| MutableList | subList | int |
| MutableMap | compute | BiFunction<? super K,? super V,? extends V> |
| MutableMap | compute | K |
| MutableMap | computeIfAbsent | Function<? super K,? extends V> |
| MutableMap | computeIfAbsent | K |
| MutableMap | computeIfPresent | BiFunction<? super K,? super V,? extends V> |
| MutableMap | computeIfPresent | K |
| MutableMap | merge | BiFunction<? super V,? super V,? extends V> |
| MutableMap | merge | K |
| MutableMap | merge | V |
| MutableMap | put | K |
| MutableMap | put | V |
| MutableMap | putAll | Map<? extends K,? extends V> |
| MutableMap | putIfAbsent | K |
| MutableMap | putIfAbsent | V |
| MutableMap | remove | Object |
| MutableMap | replace | K |
| MutableMap | replace | V |
| MutableMap | replaceAll | BiFunction<? super K,? super V,? extends V> |

View File

@@ -0,0 +1,29 @@
fun test(
p1: Map<String, String>,
p2: AbstractMap<String, String>,
p3: Collection<String>,
p4: AbstractCollection<String>,
p5: List<String>,
p6: AbstractList<String>,
p7: MutableMap<String, String>,
p8: AbstractMutableMap<String, String>,
p9: MutableCollection<String>,
p10: AbstractMutableCollection<String>,
p11: MutableList<String>,
p12: AbstractMutableList<String>) {
// Use a method of each to ensure method prototypes are extracted:
p1.get("Hello");
p2.get("Hello");
p3.contains("Hello");
p4.contains("Hello");
p5.contains("Hello");
p6.contains("Hello");
p7.remove("Hello");
p8.remove("Hello");
p9.remove("Hello");
p10.remove("Hello");
p11.remove("Hello");
p12.remove("Hello");
}

View File

@@ -0,0 +1,28 @@
import java
RefType getARelevantCollectionType() {
result
.hasQualifiedName(["java.util", "kotlin.collections"],
["Abstract", ""] + ["Mutable", ""] + ["Collection", "List", "Map"])
}
class RelevantMethod extends Method {
RelevantMethod() { this.getDeclaringType().getSourceDeclaration() = getARelevantCollectionType() }
}
// Check for methods with suspicious twins -- probably another extraction of the same method outline which was given a different trap key.
// It so happens the collections methods of interest to this test don't use overloads with the same parameter count.
query predicate methodWithDuplicate(string methodName, string typeName) {
exists(RelevantMethod m, RelevantMethod dup |
dup.getName() = m.getName() and
not dup.getName() = ["of", "remove", "toArray"] and // These really do have overloads with the same parameter count, so it isn't trivial to tell if they are intentional overloads or inappropriate duplicates.
dup.getNumberOfParameters() = m.getNumberOfParameters() and
dup.getDeclaringType() = m.getDeclaringType() and
dup != m and
methodName = m.getName() and
typeName = m.getDeclaringType().getName()
)
}
from RelevantMethod m
select m.getDeclaringType().getName(), m.getName(), m.getAParamType().getName()

View File

@@ -0,0 +1,27 @@
public class Test {
byte b;
short s;
int i;
long l;
float f;
double d;
public void test(Number n, Byte b2) {
b = n.byteValue();
s = n.shortValue();
i = n.intValue();
l = n.longValue();
f = n.floatValue();
d = n.doubleValue();
b = b2.byteValue();
s = b2.shortValue();
i = b2.intValue();
l = b2.longValue();
f = b2.floatValue();
d = b2.doubleValue();
}
}

View File

@@ -0,0 +1,50 @@
| java.lang.Byte | byteValue |
| java.lang.Byte | compare |
| java.lang.Byte | compareTo |
| java.lang.Byte | compareUnsigned |
| java.lang.Byte | decode |
| java.lang.Byte | describeConstable |
| java.lang.Byte | doubleValue |
| java.lang.Byte | equals |
| java.lang.Byte | floatValue |
| java.lang.Byte | hashCode |
| java.lang.Byte | intValue |
| java.lang.Byte | longValue |
| java.lang.Byte | parseByte |
| java.lang.Byte | shortValue |
| java.lang.Byte | toString |
| java.lang.Byte | toUnsignedInt |
| java.lang.Byte | toUnsignedLong |
| java.lang.Byte | valueOf |
| java.lang.Number | byteValue |
| java.lang.Number | doubleValue |
| java.lang.Number | floatValue |
| java.lang.Number | intValue |
| java.lang.Number | longValue |
| java.lang.Number | shortValue |
| kotlin.Byte | byteValue |
| kotlin.Byte | compareTo |
| kotlin.Byte | dec |
| kotlin.Byte | describeConstable |
| kotlin.Byte | div |
| kotlin.Byte | doubleValue |
| kotlin.Byte | floatValue |
| kotlin.Byte | inc |
| kotlin.Byte | intValue |
| kotlin.Byte | longValue |
| kotlin.Byte | minus |
| kotlin.Byte | plus |
| kotlin.Byte | rangeTo |
| kotlin.Byte | rem |
| kotlin.Byte | shortValue |
| kotlin.Byte | times |
| kotlin.Byte | toChar |
| kotlin.Byte | unaryMinus |
| kotlin.Byte | unaryPlus |
| kotlin.Number | byteValue |
| kotlin.Number | doubleValue |
| kotlin.Number | floatValue |
| kotlin.Number | intValue |
| kotlin.Number | longValue |
| kotlin.Number | shortValue |
| kotlin.Number | toChar |

View File

@@ -0,0 +1 @@
fun f(n: Number, b: Byte) = n.toByte() + n.toShort() + n.toInt() + n.toLong() + n.toFloat() + n.toDouble() + b.toByte() + b.toShort() + b.toInt() + b.toLong() + b.toFloat() + b.toDouble()

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.getDeclaringType().getName() = ["Number", "Byte"]
select m.getDeclaringType().getQualifiedName(), m.toString()

View File

@@ -0,0 +1,11 @@
import java.util.AbstractList;
public class MyList<T> extends AbstractList<T> {
public T get(int idx) { return null; }
public T remove(int idx) { return null; }
public int size() { return 0; }
}

View File

@@ -0,0 +1,3 @@
| get |
| remove |
| size |

View File

@@ -0,0 +1,2 @@
fun f(l: MyList<String>) = l.get(0)

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.getDeclaringType().getName().matches("MyList%")
select m.toString()

View File

@@ -0,0 +1,3 @@
import java.util.Map;
public abstract class C<K, V> implements Map.Entry<K, V> { }

View File

@@ -0,0 +1 @@
public abstract class B<K, V> : Map.Entry<K, V> { }

View File

@@ -0,0 +1,2 @@
| comparingByKey | K | Comparable<? super K> |
| comparingByValue | V | Comparable<? super V> |

View File

@@ -0,0 +1,7 @@
import java
from Method m, TypeVariable param
where
m.getDeclaringType().getQualifiedName() = "java.util.Map$Entry" and
param = m.(GenericCallable).getATypeParameter()
select m.toString(), param.toString(), param.getATypeBound().toString()

View File

@@ -0,0 +1,2 @@
| test.kt:1:100:1:109 | mutableIterator(...) | mutableIterator |
| test.kt:3:73:3:82 | iterator(...) | iterator |

View File

@@ -0,0 +1,3 @@
fun getIter(m: MutableMap<String, Int>): MutableIterator<MutableMap.MutableEntry<String, Int>> = m.iterator()
fun getIter2(m: Map<String, Int>): Iterator<Map.Entry<String, Int>> = m.iterator()

View File

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

View File

@@ -1,4 +1,4 @@
| PropertyReferenceDelegatesKt | getValue(KProperty0<V>, Object, KProperty<?>) |
| PropertyReferenceDelegatesKt | getValue(KProperty1<T,V>, T, KProperty<?>) |
| PropertyReferenceDelegatesKt | getValue(KProperty0<? extends V>, Object, KProperty<?>) |
| PropertyReferenceDelegatesKt | getValue(KProperty1<T,? extends V>, T, KProperty<?>) |
| StringsKt | removePrefix(String, CharSequence) |
| StringsKt | startsWith(String, String, boolean) |

View File

@@ -211,9 +211,11 @@ reflection.kt:
# 102| 0: [Parameter] l
# 102| 0: [TypeAccess] T
# 102| 1: [Parameter] transform
# 102| 0: [TypeAccess] Function1<T,R>
# 102| 0: [TypeAccess] T
# 102| 1: [TypeAccess] R
# 102| 0: [TypeAccess] Function1<? super T,? extends R>
# 102| 0: [WildcardTypeAccess] ? ...
# 102| 1: [TypeAccess] T
# 102| 1: [WildcardTypeAccess] ? ...
# 102| 0: [TypeAccess] R
# 102| 5: [BlockStmt] { ... }
# 103| 8: [Method] fn12
#-----| 2: (Generic Parameters)
@@ -224,9 +226,11 @@ reflection.kt:
# 103| 0: [Parameter] l
# 103| 0: [TypeAccess] T1
# 103| 1: [Parameter] l2
# 103| 0: [TypeAccess] Function1<T1,R>
# 103| 0: [TypeAccess] T1
# 103| 1: [TypeAccess] R
# 103| 0: [TypeAccess] Function1<? super T1,? extends R>
# 103| 0: [WildcardTypeAccess] ? ...
# 103| 1: [TypeAccess] T1
# 103| 1: [WildcardTypeAccess] ? ...
# 103| 0: [TypeAccess] R
# 103| 5: [BlockStmt] { ... }
# 121| 9: [Method] fn1
# 121| 3: [TypeAccess] int
@@ -557,6 +561,7 @@ reflection.kt:
#-----| 4: (Parameters)
# 24| 0: [Parameter] it
# 24| 0: [TypeAccess] KCallable<?>
# 24| 0: [WildcardTypeAccess] ? ...
# 24| 5: [BlockStmt] { ... }
# 24| 0: [ReturnStmt] return ...
# 24| 0: [ValueEQExpr] ... (value equals) ...

View File

@@ -1,18 +1,18 @@
| NonSerializableFieldTest.java:25:8:25:19 | problematic1 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:26:14:26:25 | problematic2 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:27:16:27:27 | problematic3 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:27:16:27:27 | problematic3 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:28:16:28:27 | problematic4 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:28:16:28:27 | problematic4 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:29:30:29:41 | problematic5 | This field is in a serializable class, but is not serializable itself because Map<?,NS> is not serializable. |
| NonSerializableFieldTest.java:30:9:30:20 | problematic6 | This field is in a serializable class, but is not serializable itself because Map<> is not serializable. |
| NonSerializableFieldTest.java:31:24:31:35 | problematic7 | This field is in a serializable class, but is not serializable itself because ? extends NS is not serializable. |
| NonSerializableFieldTest.java:32:22:32:33 | problematic8 | This field is in a serializable class, but is not serializable itself because ? super NS is not serializable. |
| NonSerializableFieldTest.java:33:7:33:18 | problematic9 | This field is in a serializable class, but is not serializable itself because T is not serializable. |
| NonSerializableFieldTest.java:34:13:34:25 | problematic10 | This field is in a serializable class, but is not serializable itself because T is not serializable. |
| NonSerializableFieldTest.java:35:13:35:25 | problematic11 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:36:15:36:27 | problematic12 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:37:34:37:46 | problematic13 | This field is in a serializable class, but is not serializable itself because Map<?,Double> is not serializable. |
| NonSerializableFieldTest.java:38:21:38:33 | problematic14 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:79:10:79:20 | problematic | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:109:26:109:45 | nonSerializableField | This field is in a serializable class, but is not serializable itself because NonSerializableClass is not serializable. |
| NonSerializableFieldTest.java:25:8:25:19 | problematic1 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:26:14:26:25 | problematic2 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:27:16:27:27 | problematic3 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:27:16:27:27 | problematic3 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:28:16:28:27 | problematic4 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:28:16:28:27 | problematic4 | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:29:30:29:41 | problematic5 | This field is in a serializable class, but is not serializable itself because Map<?,NS> is not serializable. |
| NonSerializableFieldTest.java:30:9:30:20 | problematic6 | This field is in a serializable class, but is not serializable itself because Map<> is not serializable. |
| NonSerializableFieldTest.java:31:24:31:35 | problematic7 | This field is in a serializable class, but is not serializable itself because ? extends NS is not serializable. |
| NonSerializableFieldTest.java:32:22:32:33 | problematic8 | This field is in a serializable class, but is not serializable itself because ? super NS is not serializable. |
| NonSerializableFieldTest.java:33:7:33:18 | problematic9 | This field is in a serializable class, but is not serializable itself because T is not serializable. |
| NonSerializableFieldTest.java:34:13:34:25 | problematic10 | This field is in a serializable class, but is not serializable itself because T is not serializable. |
| NonSerializableFieldTest.java:35:13:35:25 | problematic11 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:36:15:36:27 | problematic12 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:37:34:37:46 | problematic13 | This field is in a serializable class, but is not serializable itself because Map<?,Double> is not serializable. |
| NonSerializableFieldTest.java:38:21:38:33 | problematic14 | This field is in a serializable class, but is not serializable itself because ? is not serializable. |
| NonSerializableFieldTest.java:79:10:79:20 | problematic | This field is in a serializable class, but is not serializable itself because NS is not serializable. |
| NonSerializableFieldTest.java:109:26:109:45 | nonSerializableField | This field is in a serializable class, but is not serializable itself because NonSerializableClass is not serializable. |