mirror of
https://github.com/github/codeql.git
synced 2026-07-20 10:48:17 +02:00
Merge branch main into rc/3.6
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -9,7 +9,7 @@ Java framework & library support
|
||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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?>()
|
||||
}
|
||||
|
||||
|
||||
@@ -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>()
|
||||
|
||||
@@ -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()
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
90
java/kotlin-extractor/src/main/kotlin/utils/JvmNames.kt
Normal file
90
java/kotlin-extractor/src/main/kotlin/utils/JvmNames.kt
Normal 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) }
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
9
java/ql/lib/semmle/code/java/frameworks/generated.qll
Normal file
9
java/ql/lib/semmle/code/java/frameworks/generated.qll
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* A module importing all generated Models as Data models.
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
private module GeneratedFrameworks {
|
||||
private import apache.IOGenerated
|
||||
}
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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?"
|
||||
|
||||
@@ -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 + "."
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"`.
|
||||
|
||||
@@ -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> |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.fromSource()
|
||||
select m, m.getNumberOfParameters(), m.getReturnType().(RefType).getQualifiedName()
|
||||
@@ -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> {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
| |
|
||||
| <clinit> |
|
||||
| A |
|
||||
| B |
|
||||
| get |
|
||||
| getX |
|
||||
| invoke |
|
||||
| x$delegatepackagename$$subpackagename$$A |
|
||||
| x$delegatepackagename$$subpackagename$$B |
|
||||
@@ -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" }
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Class c
|
||||
where c.fromSource()
|
||||
select c.getAMember().toString()
|
||||
1
java/ql/test/kotlin/library-tests/enum/enumUser.kt
Normal file
1
java/ql/test/kotlin/library-tests/enum/enumUser.kt
Normal file
@@ -0,0 +1 @@
|
||||
fun usesEnum(e: Enum<*>) = e.ordinal.toString() + e.name
|
||||
27
java/ql/test/kotlin/library-tests/enum/test.expected
Normal file
27
java/ql/test/kotlin/library-tests/enum/test.expected
Normal 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 |
|
||||
5
java/ql/test/kotlin/library-tests/enum/test.ql
Normal file
5
java/ql/test/kotlin/library-tests/enum/test.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getDeclaringType().getName().matches("Enum%")
|
||||
select m.getName()
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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> |
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 |
|
||||
@@ -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()
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getDeclaringType().getName() = ["Number", "Byte"]
|
||||
select m.getDeclaringType().getQualifiedName(), m.toString()
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
| get |
|
||||
| remove |
|
||||
| size |
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
fun f(l: MyList<String>) = l.get(0)
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getDeclaringType().getName().matches("MyList%")
|
||||
select m.toString()
|
||||
@@ -0,0 +1,3 @@
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class C<K, V> implements Map.Entry<K, V> { }
|
||||
@@ -0,0 +1 @@
|
||||
public abstract class B<K, V> : Map.Entry<K, V> { }
|
||||
@@ -0,0 +1,2 @@
|
||||
| comparingByKey | K | Comparable<? super K> |
|
||||
| comparingByValue | V | Comparable<? super V> |
|
||||
@@ -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()
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.kt:1:100:1:109 | mutableIterator(...) | mutableIterator |
|
||||
| test.kt:3:73:3:82 | iterator(...) | iterator |
|
||||
@@ -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()
|
||||
@@ -0,0 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma, ma.getCallee().toString()
|
||||
@@ -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) |
|
||||
|
||||
@@ -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) ...
|
||||
|
||||
@@ -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. |
|
||||
|
||||
Reference in New Issue
Block a user