diff --git a/.github/workflows/js-ml-tests.yml b/.github/workflows/js-ml-tests.yml
index e6401a09c35..ba33779455e 100644
--- a/.github/workflows/js-ml-tests.yml
+++ b/.github/workflows/js-ml-tests.yml
@@ -12,6 +12,7 @@ on:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
+ workflow_dispatch:
defaults:
run:
diff --git a/config/identical-files.json b/config/identical-files.json
index d6af2fc7e1d..192144ebb4f 100644
--- a/config/identical-files.json
+++ b/config/identical-files.json
@@ -525,7 +525,8 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
- "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
+ "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
+ "python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll"
],
"IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
@@ -543,7 +544,8 @@
],
"ApiGraphModels": [
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
- "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
+ "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll",
+ "python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll"
],
"TaintedFormatStringQuery Ruby/JS": [
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql b/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
index a6fac4a40d9..d715be46bd2 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
@@ -17,6 +17,36 @@
import cpp
import semmle.code.cpp.dataflow.DataFlow
+/**
+ * A Linux system call.
+ */
+class SystemCallFunction extends Function {
+ SystemCallFunction() {
+ exists(MacroInvocation m |
+ m.getMacro().getName().matches("SYSCALL\\_DEFINE%") and
+ this = m.getEnclosingFunction()
+ )
+ }
+}
+
+/**
+ * A value that comes from a Linux system call (sources).
+ */
+class SystemCallSource extends DataFlow::Node {
+ SystemCallSource() {
+ exists(FunctionCall fc |
+ fc.getTarget() instanceof SystemCallFunction and
+ (
+ this.asDefiningArgument() = fc.getAnArgument().getAChild*() or
+ this.asExpr() = fc
+ )
+ )
+ }
+}
+
+/**
+ * Macros used to check the value (barriers).
+ */
class WriteAccessCheckMacro extends Macro {
VariableAccess va;
@@ -28,6 +58,9 @@ class WriteAccessCheckMacro extends Macro {
VariableAccess getArgument() { result = va }
}
+/**
+ * The `unsafe_put_user` macro and its uses (sinks).
+ */
class UnSafePutUserMacro extends Macro {
PointerDereferenceExpr writeUserPtr;
@@ -42,15 +75,13 @@ class UnSafePutUserMacro extends Macro {
}
}
-class ExploitableUserModePtrParam extends Parameter {
+class ExploitableUserModePtrParam extends SystemCallSource {
ExploitableUserModePtrParam() {
- not exists(WriteAccessCheckMacro writeAccessCheck |
- DataFlow::localFlow(DataFlow::parameterNode(this),
- DataFlow::exprNode(writeAccessCheck.getArgument()))
- ) and
exists(UnSafePutUserMacro unsafePutUser |
- DataFlow::localFlow(DataFlow::parameterNode(this),
- DataFlow::exprNode(unsafePutUser.getUserModePtr()))
+ DataFlow::localFlow(this, DataFlow::exprNode(unsafePutUser.getUserModePtr()))
+ ) and
+ not exists(WriteAccessCheckMacro writeAccessCheck |
+ DataFlow::localFlow(this, DataFlow::exprNode(writeAccessCheck.getArgument()))
)
}
}
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected
index ffb7941f1cd..c81cfd254df 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected
@@ -1 +1,3 @@
-| test.cpp:14:16:14:16 | p | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:14:16:14:16 | p | p |
+| test.cpp:20:21:20:22 | ref arg & ... | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:20:21:20:22 | ref arg & ... | ref arg & ... |
+| test.cpp:41:21:41:22 | ref arg & ... | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:41:21:41:22 | ref arg & ... | ref arg & ... |
+| test.cpp:69:21:69:27 | ref arg & ... | unsafe_put_user write user-mode pointer $@ without check. | test.cpp:69:21:69:27 | ref arg & ... | ref arg & ... |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp
index 755a73864c7..277b9a545e2 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp
@@ -1,7 +1,11 @@
typedef unsigned long size_t;
-void SYSC_SOMESYSTEMCALL(void *param);
+#define SYSCALL_DEFINE(name, ...) \
+ void do_sys_##name(); \
+ void sys_##name(...) { do_sys_##name(); } \
+ void do_sys_##name()
+SYSCALL_DEFINE(somesystemcall, void *param) {};
bool user_access_begin_impl(const void *where, size_t sz);
void user_access_end_impl();
@@ -13,14 +17,14 @@ void unsafe_put_user_impl(int what, const void *where, size_t sz);
void test1(int p)
{
- SYSC_SOMESYSTEMCALL(&p);
+ sys_somesystemcall(&p);
unsafe_put_user(123, &p); // BAD
}
void test2(int p)
{
- SYSC_SOMESYSTEMCALL(&p);
+ sys_somesystemcall(&p);
if (user_access_begin(&p, sizeof(p)))
{
@@ -34,16 +38,16 @@ void test3()
{
int v;
- SYSC_SOMESYSTEMCALL(&v);
+ sys_somesystemcall(&v);
- unsafe_put_user(123, &v); // BAD [NOT DETECTED]
+ unsafe_put_user(123, &v); // BAD
}
void test4()
{
int v;
- SYSC_SOMESYSTEMCALL(&v);
+ sys_somesystemcall(&v);
if (user_access_begin(&v, sizeof(v)))
{
@@ -62,16 +66,16 @@ void test5()
{
data myData;
- SYSC_SOMESYSTEMCALL(&myData);
+ sys_somesystemcall(&myData);
- unsafe_put_user(123, &(myData.x)); // BAD [NOT DETECTED]
+ unsafe_put_user(123, &(myData.x)); // BAD
}
void test6()
{
data myData;
- SYSC_SOMESYSTEMCALL(&myData);
+ sys_somesystemcall(&myData);
if (user_access_begin(&myData, sizeof(myData)))
{
diff --git a/csharp/documentation/library-coverage/coverage.csv b/csharp/documentation/library-coverage/coverage.csv
index 4d9996c1446..2bc6ca863ac 100644
--- a/csharp/documentation/library-coverage/coverage.csv
+++ b/csharp/documentation/library-coverage/coverage.csv
@@ -1,10 +1,27 @@
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint,summary:value
Dapper,55,,,,,,55,,,,
+JsonToItemsTaskFactory,,,7,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,,
+Microsoft.CSharp,,,24,,,,,,,24,
Microsoft.EntityFrameworkCore,6,,,,,,6,,,,
-Microsoft.Extensions.Primitives,,,54,,,,,,,54,
-Microsoft.VisualBasic,,,4,,,,,,,,4
+Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,15,
+Microsoft.Extensions.Caching.Memory,,,46,,,,,,,45,1
+Microsoft.Extensions.Configuration,,,83,,,,,,,80,3
+Microsoft.Extensions.DependencyInjection,,,62,,,,,,,62,
+Microsoft.Extensions.DependencyModel,,,12,,,,,,,12,
+Microsoft.Extensions.FileProviders,,,15,,,,,,,15,
+Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,13,2
+Microsoft.Extensions.Hosting,,,17,,,,,,,16,1
+Microsoft.Extensions.Http,,,10,,,,,,,10,
+Microsoft.Extensions.Logging,,,37,,,,,,,37,
+Microsoft.Extensions.Options,,,8,,,,,,,8,
+Microsoft.Extensions.Primitives,,,63,,,,,,,63,
+Microsoft.Interop,,,27,,,,,,,27,
+Microsoft.NET.Build.Tasks,,,1,,,,,,,1,
+Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,4,
+Microsoft.VisualBasic,,,9,,,,,,,5,4
+Microsoft.Win32,,,8,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,48,,,,
Newtonsoft.Json,,,91,,,,,,,73,18
ServiceStack,194,,7,27,,75,92,,,7,
-System,28,3,2336,,4,,23,1,3,611,1725
+System,28,3,12038,,4,,23,1,3,10096,1942
diff --git a/csharp/documentation/library-coverage/coverage.rst b/csharp/documentation/library-coverage/coverage.rst
index 9863b503fbf..076d2078d4b 100644
--- a/csharp/documentation/library-coverage/coverage.rst
+++ b/csharp/documentation/library-coverage/coverage.rst
@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack `_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
- System,"``System.*``, ``System``",3,2336,28,5
- Others,"``Dapper``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Primitives``, ``Microsoft.VisualBasic``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``",,149,137,
- Totals,,3,2492,359,5
+ System,"``System.*``, ``System``",3,12038,28,5
+ Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``",,554,137,
+ Totals,,3,12599,359,5
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 50dd8fb22cc..aa60cb24e79 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -226,7 +226,8 @@ commands that you can specify for compiled languages.
- Java project built using Gradle::
- codeql database create java-database --language=java --command='gradle clean test'
+ # Use `--no-daemon` because a build delegated to an existing daemon cannot be detected by CodeQL:
+ codeql database create java-database --language=java --command='gradle --no-daemon clean test'
- Java project built using Maven::
diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst
index a5f68cb64e1..4dfadcfb276 100644
--- a/docs/codeql/support/reusables/versions-compilers.rst
+++ b/docs/codeql/support/reusables/versions-compilers.rst
@@ -20,10 +20,10 @@
Java,"Java 7 to 18 [4]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [5]_",``.java``
- JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
+ JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py``
Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
- TypeScript [8]_,"2.6-4.6",Standard TypeScript compiler,"``.ts``, ``.tsx``"
+ TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group
diff --git a/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java b/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java
index 01861bf5ca6..73dc090f69b 100644
--- a/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java
+++ b/java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java
@@ -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> jarFileEntryTimeStamps = new HashMap<>();
+
+ private static Map getZipFileEntryTimeStamps(String path, Logger log) {
+ try {
+ Map 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 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);
diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
index ddce450a887..e32e5ef1974 100644
--- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
+++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
@@ -135,7 +135,7 @@ open class KotlinFileExtractor(
Unit
}
is IrField -> {
- val parentId = useDeclarationParent(declaration.parent, false)?.cast()
+ val parentId = useDeclarationParent(getFieldParent(declaration), false)?.cast()
if (parentId != null) {
extractField(declaration, parentId)
}
@@ -759,7 +759,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 +830,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)
+ }
}
}
diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
index 150e355e44d..14515cb85ed 100644
--- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
+++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
@@ -6,6 +6,7 @@ import com.semmle.extractor.java.OdasaOutput
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
+import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation
import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.*
@@ -1269,9 +1270,34 @@ open class KotlinUsesExtractor(
fun useValueParameter(vp: IrValueParameter, parent: Label?): Label =
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 =
diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
index 8fd2e4d2a30..fb04c4ede00 100644
--- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
@@ -1,7 +1,9 @@
/**
* @name Capture sink models.
* @description Finds public methods that act as sinks as they flow into a a known sink.
+ * @kind diagnostic
* @id java/utils/model-generator/sink-models
+ * @tags model-generator
*/
private import internal.CaptureModels
diff --git a/java/ql/src/utils/model-generator/CaptureSourceModels.ql b/java/ql/src/utils/model-generator/CaptureSourceModels.ql
index 49e9cb34990..d37cf5e78fb 100644
--- a/java/ql/src/utils/model-generator/CaptureSourceModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSourceModels.ql
@@ -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
diff --git a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
index 8f4eab20722..253c3d4ed46 100644
--- a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
@@ -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
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected
new file mode 100644
index 00000000000..72fe7124394
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected
@@ -0,0 +1,9 @@
+| |
+| |
+| A |
+| B |
+| get |
+| getX |
+| invoke |
+| x$delegatepackagename$$subpackagename$$A |
+| x$delegatepackagename$$subpackagename$$B |
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt
new file mode 100644
index 00000000000..9a7c5d51801
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt
@@ -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" }
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql
new file mode 100644
index 00000000000..4c0a8d53b1f
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql
@@ -0,0 +1,5 @@
+import java
+
+from Class c
+where c.fromSource()
+select c.getAMember().toString()
diff --git a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
index 4a93ee5df3b..4fdd6b4d718 100644
--- a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
@@ -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]
-# 87| 5: [FieldDeclaration] KMutableProperty0 extDelegated$delegate;
+# 87| 5: [FieldDeclaration] KMutableProperty0 extDelegated$delegateMyClass;
# 87| -1: [TypeAccess] KMutableProperty0
# 87| 0: [TypeAccess] Integer
# 87| 0: [PropertyRefExpr] ...::...
diff --git a/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected b/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
index c60b200a2eb..7141b6d1531 100644
--- a/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
@@ -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 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:///Lazy.class:0:0:0:0 | Lazy |
| delegatedProperties.kt:19:9:19:51 | varResource1 | file://:0:0:0:0 | int | delegatedProperties.kt:45:1:51:1 | ResourceDelegate |
diff --git a/java/ql/test/kotlin/library-tests/exprs/exprs.expected b/java/ql/test/kotlin/library-tests/exprs/exprs.expected
index a2a1e3bd941..110d9e47147 100644
--- a/java/ql/test/kotlin/library-tests/exprs/exprs.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/exprs.expected
@@ -830,9 +830,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 | | 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 | | 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 | | TypeAccess |
diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json
index 3053bcef1bf..6898986e749 100644
--- a/javascript/extractor/lib/typescript/package.json
+++ b/javascript/extractor/lib/typescript/package.json
@@ -2,7 +2,7 @@
"name": "typescript-parser-wrapper",
"private": true,
"dependencies": {
- "typescript": "4.6.2"
+ "typescript": "4.7.2"
},
"scripts": {
"build": "tsc --project tsconfig.json",
diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock
index f7d0c40fed8..3a10c8452f0 100644
--- a/javascript/extractor/lib/typescript/yarn.lock
+++ b/javascript/extractor/lib/typescript/yarn.lock
@@ -6,7 +6,7 @@
version "12.7.11"
resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446
-typescript@4.6.2:
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
- integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
+typescript@4.7.2:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
+ integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
diff --git a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
index fa996f1b34e..d094f05653d 100644
--- a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
+++ b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
@@ -141,8 +141,9 @@ public class Fetcher {
entryPath = entryPath.subpath(1, entryPath.getNameCount());
String filename = entryPath.getFileName().toString();
- if (!filename.endsWith(".d.ts") && !filename.equals("package.json")) {
- continue; // Only extract .d.ts files and package.json
+ if (!filename.endsWith(".d.ts") && !filename.endsWith(".d.mts") && !filename.endsWith(".d.cts")
+ && !filename.equals("package.json")) {
+ continue; // Only extract .d.ts, .d.mts, .d.cts files, and package.json
}
relativePaths.add(entryPath);
Path outputFile = destDir.resolve(entryPath);
diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
index 1e9b7d6ad84..bc30d83690d 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
@@ -203,7 +203,7 @@ public class FileExtractor {
}
},
- TYPESCRIPT(".ts", ".tsx") {
+ TYPESCRIPT(".ts", ".tsx", ".mts", ".cts") {
@Override
protected boolean contains(File f, String lcExt, ExtractorConfig config) {
if (config.getTypeScriptMode() == TypeScriptMode.NONE) return false;
diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java
index 5b425ab8af9..e5196ae1181 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/Main.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java
@@ -43,7 +43,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
- public static final String EXTRACTOR_VERSION = "2022-02-22";
+ public static final String EXTRACTOR_VERSION = "2022-05-24";
public static final Pattern NEWLINE = Pattern.compile("\n");
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
index ca7f12b7a33..f146f569684 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
@@ -144,9 +144,9 @@ private module AccessPaths {
not param = base.getReceiver()
|
result = param and
- name = param.getAnImmediateUse().asExpr().(Parameter).getName()
+ name = param.asSource().asExpr().(Parameter).getName()
or
- param.getAnImmediateUse().asExpr() instanceof DestructuringPattern and
+ param.asSource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
index 9e154c1b7d9..64406dd8eeb 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-lib
-version: 0.2.1
+version: 0.3.1
extractor: javascript
library: true
groups:
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml
index 89ae6183055..4cf8ca1dbef 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/model/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-model
-version: 0.1.1
+version: 0.2.1
groups:
- javascript
- experimental
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/codeql-pack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/codeql-pack.lock.yml
index 304d32a3b4f..9486bf8ef42 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/codeql-pack.lock.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/codeql-pack.lock.yml
@@ -1,6 +1,6 @@
---
dependencies:
codeql/javascript-experimental-atm-model:
- version: 0.1.0
+ version: 0.2.0
compiled: false
lockVersion: 1.0.0
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml
index d12e0b4ab75..bb195f22f90 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/qlpack.yml
@@ -6,4 +6,4 @@ groups:
- experimental
dependencies:
codeql/javascript-experimental-atm-lib: "*"
- codeql/javascript-experimental-atm-model: "0.1.0"
+ codeql/javascript-experimental-atm-model: "0.2.0"
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-pack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-pack.lock.yml
index 304d32a3b4f..9486bf8ef42 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-pack.lock.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-pack.lock.yml
@@ -1,6 +1,6 @@
---
dependencies:
codeql/javascript-experimental-atm-model:
- version: 0.1.0
+ version: 0.2.0
compiled: false
lockVersion: 1.0.0
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
index c3fb23e887b..e344fc6f98d 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
@@ -1,6 +1,6 @@
name: codeql/javascript-experimental-atm-queries
language: javascript
-version: 0.2.1
+version: 0.3.1
suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
groups:
@@ -8,4 +8,4 @@ groups:
- experimental
dependencies:
codeql/javascript-experimental-atm-lib: "*"
- codeql/javascript-experimental-atm-model: "0.1.0"
+ codeql/javascript-experimental-atm-model: "0.2.0"
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/test/codeql-pack.lock.yml b/javascript/ql/experimental/adaptivethreatmodeling/test/codeql-pack.lock.yml
index 304d32a3b4f..9486bf8ef42 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/test/codeql-pack.lock.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/test/codeql-pack.lock.yml
@@ -1,6 +1,6 @@
---
dependencies:
codeql/javascript-experimental-atm-model:
- version: 0.1.0
+ version: 0.2.0
compiled: false
lockVersion: 1.0.0
diff --git a/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md b/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md
new file mode 100644
index 00000000000..389b7c9044b
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* All new ECMAScript 2022 features are now supported.
diff --git a/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md
new file mode 100644
index 00000000000..16fe46c675f
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md
@@ -0,0 +1,4 @@
+---
+category: majorAnalysis
+---
+* Added support for TypeScript 4.7.
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 51101e3182a..205ff21d1fd 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -2,11 +2,7 @@
* Provides an implementation of _API graphs_, which are an abstract representation of the API
* surface used and/or defined by a code base.
*
- * The nodes of the API graph represent definitions and uses of API components. The edges are
- * directed and labeled; they specify how the components represented by nodes relate to each other.
- * For example, if one of the nodes represents a definition of an API function, then there
- * will be nodes corresponding to the function's parameters, which are connected to the function
- * node by edges labeled `parameter `.
+ * See `API::Node` for more in-depth documentation.
*/
import javascript
@@ -14,50 +10,159 @@ private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
private import internal.CachedStages
/**
- * Provides classes and predicates for working with APIs defined or used in a database.
+ * Provides classes and predicates for working with the API boundary between the current
+ * codebase and external libraries.
+ *
+ * See `API::Node` for more in-depth documentation.
*/
module API {
/**
- * An abstract representation of a definition or use of an API component such as a function
- * exported by an npm package, a parameter of such a function, or its result.
+ * A node in the API graph, representing a value that has crossed the boundary between this
+ * codebase and an external library (or in general, any external codebase).
+ *
+ * ### Basic usage
+ *
+ * API graphs are typically used to identify "API calls", that is, calls to an external function
+ * whose implementation is not necessarily part of the current codebase.
+ *
+ * The most basic use of API graphs is typically as follows:
+ * 1. Start with `API::moduleImport` for the relevant library.
+ * 2. Follow up with a chain of accessors such as `getMember` describing how to get to the relevant API function.
+ * 3. Map the resulting API graph nodes to data-flow nodes, using `asSource` or `asSink`.
+ *
+ * For example, a simplified way to get arguments to `underscore.extend` would be
+ * ```ql
+ * API::moduleImport("underscore").getMember("extend").getParameter(0).asSink()
+ * ```
+ *
+ * The most commonly used accessors are `getMember`, `getParameter`, and `getReturn`.
+ *
+ * ### API graph nodes
+ *
+ * There are two kinds of nodes in the API graphs, distinguished by who is "holding" the value:
+ * - **Use-nodes** represent values held by the current codebase, which came from an external library.
+ * (The current codebase is "using" a value that came from the library).
+ * - **Def-nodes** represent values held by the external library, which came from this codebase.
+ * (The current codebase "defines" the value seen by the library).
+ *
+ * API graph nodes are associated with data-flow nodes in the current codebase.
+ * (Since external libraries are not part of the database, there is no way to associate with concrete
+ * data-flow nodes from the external library).
+ * - **Use-nodes** are associated with data-flow nodes where a value enters the current codebase,
+ * such as the return value of a call to an external function.
+ * - **Def-nodes** are associated with data-flow nodes where a value leaves the current codebase,
+ * such as an argument passed in a call to an external function.
+ *
+ *
+ * ### Access paths and edge labels
+ *
+ * Nodes in the API graph are associated with a set of access paths, describing a series of operations
+ * that may be performed to obtain that value.
+ *
+ * For example, the access path `API::moduleImport("lodash").getMember("extend")` represents the action of
+ * importing `lodash` and then accessing the member `extend` on the resulting object.
+ * It would be associated with an expression such as `require("lodash").extend`.
+ *
+ * Each edge in the graph is labelled by such an "operation". For an edge `A->B`, the type of the `A` node
+ * determines who is performing the operation, and the type of the `B` node determines who ends up holding
+ * the result:
+ * - An edge starting from a use-node describes what the current codebase is doing to a value that
+ * came from a library.
+ * - An edge starting from a def-node describes what the external library might do to a value that
+ * came from the current codebase.
+ * - An edge ending in a use-node means the result ends up in the current codebase (at its associated data-flow node).
+ * - An edge ending in a def-node means the result ends up in external code (its associated data-flow node is
+ * the place where it was "last seen" in the current codebase before flowing out)
+ *
+ * Because the implementation of the external library is not visible, it is not known exactly what operations
+ * it will perform on values that flow there. Instead, the edges starting from a def-node are operations that would
+ * lead to an observable effect within the current codebase; without knowing for certain if the library will actually perform
+ * those operations. (When constructing these edges, we assume the library is somewhat well-behaved).
+ *
+ * For example, given this snippet:
+ * ```js
+ * require('foo')(x => { doSomething(x) })
+ * ```
+ * A callback is passed to the external function `foo`. We can't know if `foo` will actually invoke this callback.
+ * But _if_ the library should decide to invoke the callback, then a value will flow into the current codebase via the `x` parameter.
+ * For that reason, an edge is generated representing the argument-passing operation that might be performed by `foo`.
+ * This edge is going from the def-node associated with the callback to the use-node associated with the parameter `x`.
+ *
+ * ### Thinking in operations versus code patterns
+ *
+ * Treating edges as "operations" helps avoid a pitfall in which library models become overly specific to certain code patterns.
+ * Consider the following two equivalent calls to `foo`:
+ * ```js
+ * const foo = require('foo');
+ *
+ * foo({
+ * myMethod(x) {...}
+ * });
+ *
+ * foo({
+ * get myMethod() {
+ * return function(x) {...}
+ * }
+ * });
+ * ```
+ * If `foo` calls `myMethod` on its first parameter, either of the `myMethod` implementations will be invoked.
+ * And indeed, the access path `API::moduleImport("foo").getParameter(0).getMember("myMethod").getParameter(0)` correctly
+ * identifies both `x` parameters.
+ *
+ * Observe how `getMember("myMethod")` behaves when the member is defined via a getter. When thinking in code patterns,
+ * it might seem obvious that `getMember` should have obtained a reference to the getter method itself.
+ * But when seeing it as an access to `myMethod` performed by the library, we can deduce that the relevant expression
+ * on the client side is actually the return-value of the getter.
+ *
+ * Although one may think of API graphs as a tool to find certain program elements in the codebase,
+ * it can lead to some situations where intuition does not match what works best in practice.
*/
class Node extends Impl::TApiNode {
/**
- * Gets a data-flow node corresponding to a use of the API component represented by this node.
+ * Get a data-flow node where this value may flow after entering the current codebase.
*
- * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the
- * `fs` module, and `require('fs').readFileSync(file)` is a use of the return of that function.
- *
- * This includes indirect uses found via data flow, meaning that in
- * `f(obj.foo); function f(x) {};` both `obj.foo` and `x` are uses of the `foo` member from `obj`.
- *
- * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to
- * `x` are uses of the first parameter of `plusOne`.
+ * This is similar to `asSource()` but additionally includes nodes that are transitively reachable by data flow.
+ * See `asSource()` for examples.
*/
pragma[inline]
- DataFlow::Node getAUse() {
- exists(DataFlow::SourceNode src | Impl::use(this, src) |
- Impl::trackUseNode(src).flowsTo(result)
- )
+ DataFlow::Node getAValueReachableFromSource() {
+ Impl::trackUseNode(this.asSource()).flowsTo(result)
}
/**
- * Gets an immediate use of the API component represented by this node.
+ * Get a data-flow node where this value enters the current codebase.
*
- * For example, `require('fs').readFileSync` is a an immediate use of the `readFileSync` member
- * from the `fs` module.
+ * For example:
+ * ```js
+ * // API::moduleImport("fs").asSource()
+ * require('fs');
*
- * Unlike `getAUse()`, this predicate only gets the immediate references, not the indirect uses
- * found via data flow. This means that in `const x = fs.readFile` only `fs.readFile` is a reference
- * to the `readFile` member of `fs`, neither `x` nor any node that `x` flows to is a reference to
- * this API component.
+ * // API::moduleImport("fs").getMember("readFile").asSource()
+ * require('fs').readFile;
+ *
+ * // API::moduleImport("fs").getMember("readFile").getReturn().asSource()
+ * require('fs').readFile();
+ *
+ * require('fs').readFile(
+ * filename,
+ * // 'y' matched by API::moduleImport("fs").getMember("readFile").getParameter(1).getParameter(0).asSource()
+ * y => {
+ * ...
+ * });
+ * ```
*/
- DataFlow::SourceNode getAnImmediateUse() { Impl::use(this, result) }
+ DataFlow::SourceNode asSource() { Impl::use(this, result) }
+
+ /** DEPRECATED. This predicate has been renamed to `asSource`. */
+ deprecated DataFlow::SourceNode getAnImmediateUse() { result = this.asSource() }
+
+ /** DEPRECATED. This predicate has been renamed to `getAValueReachableFromSource`. */
+ deprecated DataFlow::Node getAUse() { result = this.getAValueReachableFromSource() }
/**
* Gets a call to the function represented by this API component.
*/
- CallNode getACall() { result = this.getReturn().getAnImmediateUse() }
+ CallNode getACall() { result = this.getReturn().asSource() }
/**
* Gets a call to the function represented by this API component,
@@ -72,7 +177,7 @@ module API {
/**
* Gets a `new` call to the function represented by this API component.
*/
- NewNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
+ NewNode getAnInstantiation() { result = this.getInstance().asSource() }
/**
* Gets an invocation (with our without `new`) to the function represented by this API component.
@@ -80,26 +185,38 @@ module API {
InvokeNode getAnInvocation() { result = this.getACall() or result = this.getAnInstantiation() }
/**
- * Gets a data-flow node corresponding to the right-hand side of a definition of the API
- * component represented by this node.
+ * Get a data-flow node where this value leaves the current codebase and flows into an
+ * external library (or in general, any external codebase).
*
- * For example, in the assignment `exports.plusOne = (x) => x+1`, the function expression
- * `(x) => x+1` is the right-hand side of the definition of the member `plusOne` of
- * the enclosing module, and the expression `x+1` is the right-had side of the definition of
- * its result.
+ * Concretely, this is either an argument passed to a call to external code,
+ * or the right-hand side of a property write on an object flowing into such a call.
*
- * Note that for parameters, it is the arguments flowing into that parameter that count as
- * right-hand sides of the definition, not the declaration of the parameter itself.
- * Consequently, in `require('fs').readFileSync(file)`, `file` is the right-hand
- * side of a definition of the first parameter of `readFileSync` from the `fs` module.
+ * For example:
+ * ```js
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).asSink()
+ * require('foo')(x);
+ *
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).getMember("prop").asSink()
+ * require('foo')({
+ * prop: x
+ * });
+ * ```
*/
- DataFlow::Node getARhs() { Impl::rhs(this, result) }
+ DataFlow::Node asSink() { Impl::rhs(this, result) }
/**
- * Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition
- * of the API component represented by this node.
+ * Get a data-flow node that transitively flows to an external library (or in general, any external codebase).
+ *
+ * This is similar to `asSink()` but additionally includes nodes that transitively reach a sink by data flow.
+ * See `asSink()` for examples.
*/
- DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(this.getARhs()) }
+ DataFlow::Node getAValueReachingSink() { result = Impl::trackDefNode(this.asSink()) }
+
+ /** DEPRECATED. This predicate has been renamed to `asSink`. */
+ deprecated DataFlow::Node getARhs() { result = this.asSink() }
+
+ /** DEPRECATED. This predicate has been renamed to `getAValueReachingSink`. */
+ deprecated DataFlow::Node getAValueReachingRhs() { result = this.getAValueReachingSink() }
/**
* Gets a node representing member `m` of this API component.
@@ -334,7 +451,7 @@ module API {
* In other words, the value of a use of `that` may flow into the right-hand side of a
* definition of this node.
*/
- predicate refersTo(Node that) { this.getARhs() = that.getAUse() }
+ predicate refersTo(Node that) { this.asSink() = that.getAValueReachableFromSource() }
/**
* Gets the data-flow node that gives rise to this node, if any.
@@ -445,11 +562,17 @@ module API {
bindingset[this]
EntryPoint() { any() }
- /** Gets a data-flow node that uses this entry point. */
- abstract DataFlow::SourceNode getAUse();
+ /** DEPRECATED. This predicate has been renamed to `getASource`. */
+ deprecated DataFlow::SourceNode getAUse() { none() }
- /** Gets a data-flow node that defines this entry point. */
- abstract DataFlow::Node getARhs();
+ /** DEPRECATED. This predicate has been renamed to `getASink`. */
+ deprecated DataFlow::SourceNode getARhs() { none() }
+
+ /** Gets a data-flow node where a value enters the current codebase through this entry-point. */
+ DataFlow::SourceNode getASource() { none() }
+
+ /** Gets a data-flow node where a value leaves the current codebase through this entry-point. */
+ DataFlow::Node getASink() { none() }
/** Gets an API-node for this entry point. */
API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) }
@@ -567,7 +690,7 @@ module API {
base = MkRoot() and
exists(EntryPoint e |
lbl = Label::entryPoint(e) and
- rhs = e.getARhs()
+ rhs = e.getASink()
)
or
exists(string m, string prop |
@@ -744,7 +867,7 @@ module API {
base = MkRoot() and
exists(EntryPoint e |
lbl = Label::entryPoint(e) and
- ref = e.getAUse()
+ ref = e.getASource()
)
or
// property reads
@@ -1178,8 +1301,8 @@ module API {
API::Node callee;
InvokeNode() {
- this = callee.getReturn().getAnImmediateUse() or
- this = callee.getInstance().getAnImmediateUse() or
+ this = callee.getReturn().asSource() or
+ this = callee.getInstance().asSource() or
this = Impl::getAPromisifiedInvocation(callee, _, _)
}
@@ -1194,7 +1317,7 @@ module API {
* Gets an API node where a RHS of the node is the `i`th argument to this call.
*/
pragma[noinline]
- private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) }
+ private Node getAParameterCandidate(int i) { result.asSink() = this.getArgument(i) }
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = this.getParameter(_) }
@@ -1205,13 +1328,13 @@ module API {
/** Gets the API node for the return value of this call. */
Node getReturn() {
result = callee.getReturn() and
- result.getAnImmediateUse() = this
+ result.asSource() = this
}
/** Gets the API node for the object constructed by this invocation. */
Node getInstance() {
result = callee.getInstance() and
- result.getAnImmediateUse() = this
+ result.asSource() = this
}
}
diff --git a/javascript/ql/lib/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll
index 0433b1b5681..c129e9a31b2 100644
--- a/javascript/ql/lib/semmle/javascript/Arrays.qll
+++ b/javascript/ql/lib/semmle/javascript/Arrays.qll
@@ -75,7 +75,7 @@ module ArrayTaintTracking {
succ.(DataFlow::SourceNode).getAMethodCall("splice") = call
or
// `e = array.pop()`, `e = array.shift()`, or similar: if `array` is tainted, then so is `e`.
- call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice"]) and
+ call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice", "at"]) and
succ = call
or
// `e = Array.from(x)`: if `x` is tainted, then so is `e`.
@@ -199,13 +199,13 @@ private module ArrayDataFlow {
}
/**
- * A step for retrieving an element from an array using `.pop()` or `.shift()`.
+ * A step for retrieving an element from an array using `.pop()`, `.shift()`, or `.at()`.
* E.g. `array.pop()`.
*/
private class ArrayPopStep extends DataFlow::SharedFlowStep {
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
exists(DataFlow::MethodCallNode call |
- call.getMethodName() = ["pop", "shift"] and
+ call.getMethodName() = ["pop", "shift", "at"] and
prop = arrayElement() and
obj = call.getReceiver() and
element = call
diff --git a/javascript/ql/lib/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
index 35a227c3ad8..e3f1f285a21 100644
--- a/javascript/ql/lib/semmle/javascript/JsonParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
@@ -29,7 +29,7 @@ private class PlainJsonParserCall extends JsonParserCall {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"parse") or
- callee = API::moduleImport("replicator").getInstance().getMember("decode").getAnImmediateUse() or
+ callee = API::moduleImport("replicator").getInstance().getMember("decode").asSource() or
callee = DataFlow::moduleImport("parse-json") or
callee = DataFlow::moduleImport("json-parse-better-errors") or
callee = DataFlow::moduleImport("json-safe-parse") or
diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
index bf45bcdd7b4..a298abfd2dd 100644
--- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
@@ -134,7 +134,7 @@ module JsonSchema {
.ref()
.getMember(["addSchema", "validate", "compile", "compileAsync"])
.getParameter(0)
- .getARhs()
+ .asSink()
}
}
}
@@ -184,7 +184,7 @@ module JsonSchema {
override boolean getPolarity() { none() }
override DataFlow::Node getAValidationResultAccess(boolean polarity) {
- result = this.getReturn().getMember("error").getAnImmediateUse() and
+ result = this.getReturn().getMember("error").asSource() and
polarity = false
}
}
diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
index 03ca152471f..f4cdda89e31 100644
--- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
@@ -14,7 +14,7 @@ class JsonStringifyCall extends DataFlow::CallNode {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"stringify") or
- callee = API::moduleImport("replicator").getInstance().getMember("encode").getAnImmediateUse() or
+ callee = API::moduleImport("replicator").getInstance().getMember("encode").asSource() or
callee =
DataFlow::moduleImport([
"json-stringify-safe", "json-stable-stringify", "stringify-object",
diff --git a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
index 6c51b487f43..607c55c9d02 100644
--- a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
+++ b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
@@ -229,10 +229,10 @@ module MembershipCandidate {
membersNode = inExpr.getRightOperand()
)
or
- exists(MethodCallExpr hasOwn |
- this = hasOwn.getArgument(0).flow() and
- test = hasOwn and
- hasOwn.calls(membersNode, "hasOwnProperty")
+ exists(HasOwnPropertyCall hasOwn |
+ this = hasOwn.getProperty() and
+ test = hasOwn.asExpr() and
+ membersNode = hasOwn.getObject().asExpr()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
index d99cd0e7e0d..9366c76d9cc 100644
--- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
+++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
@@ -192,3 +192,35 @@ class StringSplitCall extends DataFlow::MethodCallNode {
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = this.getAPropertyRead(i.toString()) }
}
+
+/**
+ * A call to `Object.prototype.hasOwnProperty`, `Object.hasOwn`, or a library that implements
+ * the same functionality.
+ */
+class HasOwnPropertyCall extends DataFlow::Node instanceof DataFlow::CallNode {
+ DataFlow::Node object;
+ DataFlow::Node property;
+
+ HasOwnPropertyCall() {
+ // Make sure we handle reflective calls since libraries love to do that.
+ super.getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() =
+ "hasOwnProperty" and
+ object = super.getReceiver() and
+ property = super.getArgument(0)
+ or
+ this =
+ [
+ DataFlow::globalVarRef("Object").getAMemberCall("hasOwn"), //
+ DataFlow::moduleImport("has").getACall(), //
+ LodashUnderscore::member("has").getACall()
+ ] and
+ object = super.getArgument(0) and
+ property = super.getArgument(1)
+ }
+
+ /** Gets the object whose property is being checked. */
+ DataFlow::Node getObject() { result = object }
+
+ /** Gets the property being checked. */
+ DataFlow::Node getProperty() { result = property }
+}
diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll
index 70a1ed98830..2a0ce9464fb 100644
--- a/javascript/ql/lib/semmle/javascript/TypeScript.qll
+++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll
@@ -1286,6 +1286,8 @@ class ExpressionWithTypeArguments extends @expression_with_type_arguments, Expr
override ControlFlowNode getFirstControlFlowNode() {
result = this.getExpression().getFirstControlFlowNode()
}
+
+ override string getAPrimaryQlClass() { result = "ExpressionWithTypeArguments" }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
index dde1c004946..0f82ec2e8e6 100644
--- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
+++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
@@ -1027,18 +1027,16 @@ module TaintTracking {
class WhitelistContainmentCallSanitizer extends AdditionalSanitizerGuardNode,
DataFlow::MethodCallNode {
WhitelistContainmentCallSanitizer() {
- exists(string name |
- name = "contains" or
- name = "has" or
- name = "hasOwnProperty"
- |
- this.getMethodName() = name
- )
+ this.getMethodName() = ["contains", "has", "hasOwnProperty", "hasOwn"]
}
override predicate sanitizes(boolean outcome, Expr e) {
- outcome = true and
- e = this.getArgument(0).asExpr()
+ exists(int propertyIndex |
+ if this.getMethodName() = "hasOwn" then propertyIndex = 1 else propertyIndex = 0
+ |
+ outcome = true and
+ e = this.getArgument(propertyIndex).asExpr()
+ )
}
override predicate appliesTo(Configuration cfg) { any() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
index 3d061eb2aef..4280862c6e0 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
@@ -198,7 +198,7 @@ module Babel {
.getMember(["transform", "transformSync", "transformAsync"])
.getACall() and
pred = call.getArgument(0) and
- succ = [call, call.getParameter(2).getParameter(0).getAnImmediateUse()]
+ succ = [call, call.getParameter(2).getParameter(0).asSource()]
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
index 7c8e4a040a4..fdc820861b1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
@@ -14,7 +14,7 @@ module Cheerio {
}
/** Gets a reference to the `cheerio` function, possibly with a loaded DOM. */
- DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAUse() }
+ DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAValueReachableFromSource() }
/**
* A creation of `cheerio` object, a collection of virtual DOM elements
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
index 381451c393c..35f966217bd 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
@@ -39,7 +39,8 @@ module ClassValidator {
/** Holds if the given field has a decorator that sanitizes its value for the purpose of taint tracking. */
predicate isFieldSanitizedByDecorator(FieldDefinition field) {
- field.getADecorator().getExpression().flow() = sanitizingDecorator().getReturn().getAUse()
+ field.getADecorator().getExpression().flow() =
+ sanitizingDecorator().getReturn().getAValueReachableFromSource()
}
pragma[noinline]
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
index e86af94463f..8e56a36b9bf 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
@@ -265,7 +265,7 @@ module ClientRequest {
or
responseType = this.getResponseType() and
promise = false and
- result = this.getReturn().getPromisedError().getMember("response").getAnImmediateUse()
+ result = this.getReturn().getPromisedError().getMember("response").asSource()
}
}
@@ -463,7 +463,7 @@ module ClientRequest {
*/
private API::Node netSocketInstantiation(DataFlow::NewNode socket) {
result = API::moduleImport("net").getMember("Socket").getInstance() and
- socket = result.getAnImmediateUse()
+ socket = result.asSource()
}
/**
@@ -827,7 +827,7 @@ module ClientRequest {
class ApolloClientRequest extends ClientRequest::Range, API::InvokeNode {
ApolloClientRequest() { this = apolloUriCallee().getAnInvocation() }
- override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").getARhs() }
+ override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").asSink() }
override DataFlow::Node getHost() { none() }
@@ -848,10 +848,10 @@ module ClientRequest {
override DataFlow::Node getUrl() { result = this.getArgument(0) }
- override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").getARhs() }
+ override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").asSink() }
override DataFlow::Node getADataNode() {
- result = form.getMember("append").getACall().getParameter(1).getARhs()
+ result = form.getMember("append").getACall().getParameter(1).asSink()
}
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
index b6892b5aa49..164bc6e8f88 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
@@ -21,7 +21,7 @@ private class CredentialsFromModel extends CredentialsExpr {
string kind;
CredentialsFromModel() {
- this = ModelOutput::getASinkNode("credentials[" + kind + "]").getARhs().asExpr()
+ this = ModelOutput::getASinkNode("credentials[" + kind + "]").asSink().asExpr()
}
override string getCredentialsKind() { result = kind }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index 1dda09dedb8..76bdeb1324a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -9,9 +9,7 @@ module D3 {
private class D3GlobalEntry extends API::EntryPoint {
D3GlobalEntry() { this = "D3GlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("d3") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("d3") }
}
/** Gets an API node referring to the `d3` module. */
@@ -71,18 +69,18 @@ module D3 {
D3XssSink() {
exists(API::Node htmlArg |
htmlArg = d3Selection().getMember("html").getParameter(0) and
- this = [htmlArg, htmlArg.getReturn()].getARhs()
+ this = [htmlArg, htmlArg.getReturn()].asSink()
)
}
}
private class D3DomValueSource extends DOM::DomValueSource::Range {
D3DomValueSource() {
- this = d3Selection().getMember("each").getReceiver().getAnImmediateUse()
+ this = d3Selection().getMember("each").getReceiver().asSource()
or
- this = d3Selection().getMember("node").getReturn().getAnImmediateUse()
+ this = d3Selection().getMember("node").getReturn().asSource()
or
- this = d3Selection().getMember("nodes").getReturn().getUnknownMember().getAnImmediateUse()
+ this = d3Selection().getMember("nodes").getReturn().getUnknownMember().asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
index 1b3ee3dfea5..038f4b8afb3 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
@@ -56,13 +56,13 @@ module Electron {
}
}
- private API::Node browserObject() { result.getAnImmediateUse() instanceof NewBrowserObject }
+ private API::Node browserObject() { result.asSource() instanceof NewBrowserObject }
/**
* A data flow node whose value may originate from a browser object instantiation.
*/
private class BrowserObjectByFlow extends BrowserObject {
- BrowserObjectByFlow() { browserObject().getAUse() = this }
+ BrowserObjectByFlow() { browserObject().getAValueReachableFromSource() = this }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
index 0bad9367b7f..f03f5ee1458 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
@@ -89,7 +89,7 @@ private API::Node globbyFileNameSource() {
* A file name or an array of file names from the `globby` library.
*/
private class GlobbyFileNameSource extends FileNameSource {
- GlobbyFileNameSource() { this = globbyFileNameSource().getAnImmediateUse() }
+ GlobbyFileNameSource() { this = globbyFileNameSource().asSource() }
}
/** Gets a file name or an array of file names from the `fast-glob` library. */
@@ -116,7 +116,7 @@ private API::Node fastGlobFileName() {
* A file name or an array of file names from the `fast-glob` library.
*/
private class FastGlobFileNameSource extends FileNameSource {
- FastGlobFileNameSource() { this = fastGlobFileName().getAnImmediateUse() }
+ FastGlobFileNameSource() { this = fastGlobFileName().asSource() }
}
/**
@@ -200,7 +200,7 @@ private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, API::
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().asSource() }
private API::Node trackFileSource() {
result = this.getParameter([1 .. 2]).getParameter(1)
@@ -223,7 +223,7 @@ private module JsonFile {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().asSource() }
private API::Node trackRead() {
this.getCalleeName() = "readFile" and
@@ -272,7 +272,7 @@ private class LoadJsonFile extends FileSystemReadAccess, API::CallNode {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().asSource() }
private API::Node trackRead() {
this.getCalleeName() = "sync" and result = this.getReturn()
@@ -310,7 +310,7 @@ private class WalkDir extends FileNameProducer, FileSystemAccess, API::CallNode
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().asSource() }
private API::Node trackFileSource() {
not this.getCalleeName() = ["sync", "async"] and
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
index c5fa208406f..26e0d4fe94f 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
@@ -15,7 +15,7 @@ private class BusBoyRemoteFlow extends RemoteFlowSource {
.getMember("on")
.getParameter(1)
.getAParameter()
- .getAnImmediateUse()
+ .asSource()
}
override string getSourceType() { result = "parsed user value from Busbuy" }
@@ -49,12 +49,12 @@ private class MultipartyRemoteFlow extends RemoteFlowSource {
MultipartyRemoteFlow() {
exists(API::Node form | form = API::moduleImport("multiparty").getMember("Form").getInstance() |
exists(API::CallNode parse | parse = form.getMember("parse").getACall() |
- this = parse.getParameter(1).getAParameter().getAnImmediateUse()
+ this = parse.getParameter(1).getAParameter().asSource()
)
or
exists(API::CallNode on | on = form.getMember("on").getACall() |
on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and
- this = on.getParameter(1).getAParameter().getAnImmediateUse()
+ this = on.getParameter(1).getAParameter().asSource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
index b4535b9bf2b..37c0057f6c1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
@@ -8,9 +8,7 @@ module History {
private class HistoryGlobalEntry extends API::EntryPoint {
HistoryGlobalEntry() { this = "HistoryLibrary" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("HistoryLibrary") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("HistoryLibrary") }
}
/**
@@ -40,11 +38,11 @@ module History {
HistoryLibraryRemoteFlow() {
exists(API::Node loc | loc = [getBrowserHistory(), getHashHistory()].getMember("location") |
- this = loc.getMember("hash").getAnImmediateUse() and kind.isFragment()
+ this = loc.getMember("hash").asSource() and kind.isFragment()
or
- this = loc.getMember("pathname").getAnImmediateUse() and kind.isPath()
+ this = loc.getMember("pathname").asSource() and kind.isPath()
or
- this = loc.getMember("search").getAnImmediateUse() and kind.isQuery()
+ this = loc.getMember("search").asSource() and kind.isQuery()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
index 2467ca0973b..24e694ca8d9 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
@@ -19,10 +19,10 @@ private module HttpProxy {
.getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").getARhs() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").asSink() }
override DataFlow::Node getHost() {
- result = getParameter(0).getMember("target").getMember("host").getARhs()
+ result = getParameter(0).getMember("target").getMember("host").asSink()
}
override DataFlow::Node getADataNode() { none() }
@@ -49,10 +49,10 @@ private module HttpProxy {
)
}
- override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").getARhs() }
+ override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").asSink() }
override DataFlow::Node getHost() {
- result = getOptionsObject().getMember("target").getMember("host").getARhs()
+ result = getOptionsObject().getMember("target").getMember("host").asSink()
}
override DataFlow::Node getADataNode() { none() }
@@ -78,8 +78,8 @@ private module HttpProxy {
ProxyListenerCallback() {
exists(API::CallNode call |
call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and
- call.getParameter(0).getARhs().mayHaveStringValue(event) and
- this = call.getParameter(1).getARhs().getAFunctionValue()
+ call.getParameter(0).asSink().mayHaveStringValue(event) and
+ this = call.getParameter(1).asSink().getAFunctionValue()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
index 39b0ea201bb..3a5ef400801 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
@@ -16,9 +16,7 @@ private module Immutable {
private class ImmutableGlobalEntry extends API::EntryPoint {
ImmutableGlobalEntry() { this = "ImmutableGlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("Immutable") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Immutable") }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
index 6f2098f27c9..e768a9feaff 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
@@ -69,7 +69,7 @@ module Knex {
private class KnexDatabaseAwait extends DatabaseAccess, DataFlow::ValueNode {
KnexDatabaseAwait() {
exists(AwaitExpr enclosingAwait | this = enclosingAwait.flow() |
- enclosingAwait.getOperand() = knexObject().getAUse().asExpr()
+ enclosingAwait.getOperand() = knexObject().getAValueReachableFromSource().asExpr()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
index 853b76afdda..1118f05b506 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
@@ -61,10 +61,10 @@ module LdapJS {
SearchFilter() {
options = ldapClient().getMember("search").getACall().getParameter(1) and
- this = options.getARhs()
+ this = options.asSink()
}
- override DataFlow::Node getInput() { result = options.getMember("filter").getARhs() }
+ override DataFlow::Node getInput() { result = options.getMember("filter").asSink() }
override DataFlow::Node getOutput() { result = this }
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
index aa365680cd2..1d7604e0b0c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
@@ -12,7 +12,7 @@ private module LiveServer {
class ServerDefinition extends HTTP::Servers::StandardServerDefinition {
ServerDefinition() { this = DataFlow::moduleImport("live-server").asExpr() }
- API::Node getImportNode() { result.getAnImmediateUse().asExpr() = this }
+ API::Node getImportNode() { result.asSource().asExpr() = this }
}
/**
@@ -41,7 +41,7 @@ private module LiveServer {
override DataFlow::SourceNode getARouteHandler() {
exists(DataFlow::SourceNode middleware |
- middleware = call.getParameter(0).getMember("middleware").getAValueReachingRhs()
+ middleware = call.getParameter(0).getMember("middleware").getAValueReachingSink()
|
result = middleware.getAMemberCall(["push", "unshift"]).getArgument(0).getAFunctionValue()
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
index aa79a35785b..8f5938f4865 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
@@ -35,9 +35,7 @@ private module Console {
private class ConsoleGlobalEntry extends API::EntryPoint {
ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("console") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("console") }
}
/**
@@ -352,7 +350,7 @@ private module Pino {
// `pino` is installed as the "log" property on the request object in `Express` and similar libraries.
// in `Hapi` the property is "logger".
exists(HTTP::RequestExpr req, API::Node reqNode |
- reqNode.getAnImmediateUse() = req.flow().getALocalSource() and
+ reqNode.asSource() = req.flow().getALocalSource() and
result = reqNode.getMember(["log", "logger"])
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
index d131c70773a..492ab0cbcec 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
@@ -163,14 +163,14 @@ module Markdown {
or
call = API::moduleImport("markdown-it").getMember("Markdown").getAnInvocation()
|
- call.getParameter(0).getMember("html").getARhs().mayHaveBooleanValue(true) and
+ call.getParameter(0).getMember("html").asSink().mayHaveBooleanValue(true) and
result = call.getReturn()
)
or
exists(API::CallNode call |
call = markdownIt().getMember(["use", "set", "configure", "enable", "disable"]).getACall() and
result = call.getReturn() and
- not call.getParameter(0).getAValueReachingRhs() =
+ not call.getParameter(0).getAValueReachingSink() =
DataFlow::moduleImport("markdown-it-sanitizer")
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index bc2bf109fdf..1799f35beb8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -140,11 +140,9 @@ module NestJS {
private class ValidationNodeEntry extends API::EntryPoint {
ValidationNodeEntry() { this = "ValidationNodeEntry" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
result.(DataFlow::ClassNode).getName() = "ValidationPipe"
}
-
- override DataFlow::Node getARhs() { none() }
}
/** Gets an API node referring to the constructor of `ValidationPipe` */
@@ -181,7 +179,7 @@ module NestJS {
predicate hasGlobalValidationPipe(Folder folder) {
exists(DataFlow::CallNode call |
call.getCalleeName() = "useGlobalPipes" and
- call.getArgument(0) = validationPipe().getInstance().getAUse() and
+ call.getArgument(0) = validationPipe().getInstance().getAValueReachableFromSource() and
folder = call.getFile().getParentContainer()
)
or
@@ -193,7 +191,7 @@ module NestJS {
.getAMember()
.getMember("useFactory")
.getReturn()
- .getARhs() = validationPipe().getInstance().getAUse() and
+ .asSink() = validationPipe().getInstance().getAValueReachableFromSource() and
folder = decorator.getFile().getParentContainer()
)
or
@@ -204,7 +202,7 @@ module NestJS {
* Holds if `param` is affected by a pipe that sanitizes inputs.
*/
private predicate hasSanitizingPipe(NestJSRequestInput param, boolean dependsOnType) {
- param.getAPipe() = sanitizingPipe(dependsOnType).getAUse()
+ param.getAPipe() = sanitizingPipe(dependsOnType).getAValueReachableFromSource()
or
hasGlobalValidationPipe(param.getFile().getParentContainer()) and
dependsOnType = true
@@ -395,11 +393,11 @@ module NestJS {
/** Gets a parameter with this decorator applied. */
DataFlow::ParameterNode getADecoratedParameter() {
- result.getADecorator() = getReturn().getReturn().getAUse()
+ result.getADecorator() = getReturn().getReturn().getAValueReachableFromSource()
}
/** Gets a value returned by the decorator's callback, which becomes the value of the decorated parameter. */
- DataFlow::Node getResult() { result = getParameter(0).getReturn().getARhs() }
+ DataFlow::Node getResult() { result = getParameter(0).getReturn().asSink() }
}
/**
@@ -427,7 +425,7 @@ module NestJS {
private class ExpressRequestSource extends Express::RequestSource {
ExpressRequestSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Req", "Request"]).getReturn().getAnImmediateUse()
+ nestjs().getMember(["Req", "Request"]).getReturn().asSource()
or
this =
executionContext()
@@ -435,7 +433,7 @@ module NestJS {
.getReturn()
.getMember("getRequest")
.getReturn()
- .getAnImmediateUse()
+ .asSource()
}
/**
@@ -452,7 +450,7 @@ module NestJS {
private class ExpressResponseSource extends Express::ResponseSource {
ExpressResponseSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Res", "Response"]).getReturn().getAnImmediateUse()
+ nestjs().getMember(["Res", "Response"]).getReturn().asSource()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
index 644754ce75e..091aa8ba1af 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
@@ -252,6 +252,6 @@ module NextJS {
.getParameter(0)
.getParameter(0)
.getMember("router")
- .getAnImmediateUse()
+ .asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
index b04467a93ec..0d2da4b10bb 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
@@ -20,7 +20,7 @@ deprecated module NoSQL = NoSql;
* Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`.
*/
private DataFlow::Node getADollarWhereProperty(API::Node queryArg) {
- result = queryArg.getMember("$where").getARhs()
+ result = queryArg.getMember("$where").asSink()
}
/**
@@ -418,7 +418,7 @@ private module Mongoose {
param = f.getParameter(0).getParameter(1)
|
exists(DataFlow::MethodCallNode pred |
- // limitation: look at the previous method call
+ // limitation: look at the previous method call
Query::MethodSignatures::returnsDocumentQuery(pred.getMethodName(), asArray) and
pred.getAMethodCall() = f.getACall()
)
@@ -501,7 +501,7 @@ private module Mongoose {
Credentials() {
exists(string prop |
- this = createConnection().getParameter(3).getMember(prop).getARhs().asExpr()
+ this = createConnection().getParameter(3).getMember(prop).asSink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -518,7 +518,7 @@ private module Mongoose {
class MongoDBQueryPart extends NoSql::Query {
MongooseFunction f;
- MongoDBQueryPart() { this = f.getQueryArgument().getARhs().asExpr() }
+ MongoDBQueryPart() { this = f.getQueryArgument().asSink().asExpr() }
override DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(f.getQueryArgument())
@@ -540,7 +540,7 @@ private module Mongoose {
override DataFlow::Node getAQueryArgument() {
// NB: the complete information is not easily accessible for deeply chained calls
- f.getQueryArgument().getARhs() = result
+ f.getQueryArgument().asSink() = result
}
override DataFlow::Node getAResult() {
@@ -770,7 +770,7 @@ private module Redis {
RedisKeyArgument() {
exists(string method, int argIndex |
QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and
- this = redis().getMember(method).getParameter(argIndex).getARhs().asExpr()
+ this = redis().getMember(method).getParameter(argIndex).asSink().asExpr()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
index 2adc68f907a..75e222730cc 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
@@ -739,7 +739,7 @@ module NodeJSLib {
methodName = ["execFile", "execFileSync", "spawn", "spawnSync", "fork"]
) and
// all of the above methods take the command as their first argument
- result = this.getParameter(0).getARhs()
+ result = this.getParameter(0).asSink()
}
override DataFlow::Node getACommandArgument() { result = this.getACommandArgument(_) }
@@ -751,7 +751,7 @@ module NodeJSLib {
override DataFlow::Node getArgumentList() {
methodName = ["execFile", "execFileSync", "fork", "spawn", "spawnSync"] and
// all of the above methods take the argument list as their second argument
- result = this.getParameter(1).getARhs()
+ result = this.getParameter(1).asSink()
}
override predicate isSync() { methodName.matches("%Sync") }
@@ -759,7 +759,7 @@ module NodeJSLib {
override DataFlow::Node getOptionsArg() {
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode and // looks like argumentlist
- not result = this.getParameter(0).getARhs() and
+ not result = this.getParameter(0).asSink() and
// fork/spawn and all sync methos always has options as the last argument
if
methodName.matches("fork%") or
@@ -768,7 +768,7 @@ module NodeJSLib {
then result = this.getLastArgument()
else
// the rest (exec/execFile) has the options argument as their second last.
- result = this.getParameter(this.getNumArgument() - 2).getARhs()
+ result = this.getParameter(this.getNumArgument() - 2).asSink()
}
}
@@ -1070,7 +1070,7 @@ module NodeJSLib {
*/
private class EventEmitterSubClass extends DataFlow::ClassNode {
EventEmitterSubClass() {
- this.getASuperClassNode() = getAnEventEmitterImport().getAUse() or
+ this.getASuperClassNode() = getAnEventEmitterImport().getAValueReachableFromSource() or
this.getADirectSuperClass() instanceof EventEmitterSubClass
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
index ec9e490159e..1277c1ee133 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
@@ -22,7 +22,7 @@ private module Prettier {
call = API::moduleImport("prettier").getMember("formatWithCursor").getACall()
|
pred = call.getArgument(0) and
- succ = call.getReturn().getMember("formatted").getAnImmediateUse()
+ succ = call.getReturn().getMember("formatted").asSource()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
index b7bef025d23..0636b8603b9 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
@@ -86,7 +86,7 @@ module Puppeteer {
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").getARhs() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").asSink() }
override DataFlow::Node getHost() { none() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index fae5a1c76d7..67901528f2b 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -58,10 +58,10 @@ module Redux {
*/
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
/** Gets a reference to the store. */
- DataFlow::SourceNode ref() { result = asApiNode().getAUse() }
+ DataFlow::SourceNode ref() { result = asApiNode().getAValueReachableFromSource() }
/** Gets an API node that refers to this store creation. */
- API::Node asApiNode() { result.getAnImmediateUse() = this }
+ API::Node asApiNode() { result.asSource() = this }
/** Gets the data flow node holding the root reducer for this store. */
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
@@ -94,7 +94,7 @@ module Redux {
}
override DataFlow::Node getReducerArg() {
- result = getParameter(0).getMember("reducer").getARhs()
+ result = getParameter(0).getMember("reducer").asSink()
}
}
}
@@ -106,7 +106,7 @@ module Redux {
private API::Node rootState() {
result instanceof RootStateSource
or
- stateStep(rootState().getAUse(), result.getAnImmediateUse())
+ stateStep(rootState().getAValueReachableFromSource(), result.asSource())
}
/**
@@ -120,7 +120,7 @@ module Redux {
accessPath = joinAccessPaths(base, prop)
)
or
- stateStep(rootStateAccessPath(accessPath).getAUse(), result.getAnImmediateUse())
+ stateStep(rootStateAccessPath(accessPath).getAValueReachableFromSource(), result.asSource())
}
/**
@@ -193,7 +193,7 @@ module Redux {
CombineReducers() { this = combineReducers().getACall() }
override DataFlow::Node getStateHandlerArg(string prop) {
- result = getParameter(0).getMember(prop).getARhs()
+ result = getParameter(0).getMember(prop).asSink()
}
}
@@ -207,7 +207,7 @@ module Redux {
*/
private class NestedCombineReducers extends DelegatingReducer, DataFlow::ObjectLiteralNode {
NestedCombineReducers() {
- this = combineReducers().getParameter(0).getAMember+().getAValueReachingRhs()
+ this = combineReducers().getParameter(0).getAMember+().getAValueReachingSink()
}
override DataFlow::Node getStateHandlerArg(string prop) {
@@ -235,7 +235,7 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(DataFlow::PropWrite write |
- result = getParameter(0).getAMember().getARhs() and
+ result = getParameter(0).getAMember().asSink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -374,7 +374,7 @@ module Redux {
CreateSliceReducer() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("reducer").getAnImmediateUse()
+ this = call.getReturn().getMember("reducer").asSource()
}
private API::Node getABuilderRef() {
@@ -385,14 +385,14 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(string name |
- result = call.getParameter(0).getMember("reducers").getMember(name).getARhs() and
- actionType = call.getReturn().getMember("actions").getMember(name).getAnImmediateUse()
+ result = call.getParameter(0).getMember("reducers").getMember(name).asSink() and
+ actionType = call.getReturn().getMember("actions").getMember(name).asSource()
)
or
// Properties of 'extraReducers':
// { extraReducers: { [action]: reducer }}
exists(DataFlow::PropWrite write |
- result = call.getParameter(0).getMember("extraReducers").getAMember().getARhs() and
+ result = call.getParameter(0).getMember("extraReducers").getAMember().asSink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -444,8 +444,8 @@ module Redux {
or
// x -> bindActionCreators({ x, ... })
exists(BindActionCreatorsCall bind, string prop |
- ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).getARhs()) and
- result = bind.getReturn().getMember(prop).getAnImmediateUse()
+ ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and
+ result = bind.getReturn().getMember(prop).asSource()
)
or
// x -> combineActions(x, ...)
@@ -580,11 +580,11 @@ module Redux {
MultiAction() {
createActions = API::moduleImport("redux-actions").getMember("createActions").getACall() and
- this = createActions.getReturn().getMember(name).getAnImmediateUse()
+ this = createActions.getReturn().getMember(name).asSource()
}
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
- result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).getARhs()) and
+ result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).asSink()) and
async = false
}
@@ -614,12 +614,12 @@ module Redux {
CreateSliceAction() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("actions").getMember(actionName).getAnImmediateUse()
+ this = call.getReturn().getMember("actions").getMember(actionName).asSource()
}
override string getTypeTag() {
exists(string prefix |
- call.getParameter(0).getMember("name").getARhs().mayHaveStringValue(prefix) and
+ call.getParameter(0).getMember("name").asSink().mayHaveStringValue(prefix) and
result = prefix + "/" + actionName
)
}
@@ -640,7 +640,7 @@ module Redux {
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
async = true and
- result = getParameter(1).getAValueReachingRhs()
+ result = getParameter(1).getAValueReachingSink()
}
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) }
@@ -885,12 +885,12 @@ module Redux {
accessPath = getAffectedStateAccessPath(reducer)
|
pred = function.getReturnNode() and
- succ = rootStateAccessPath(accessPath).getAnImmediateUse()
+ succ = rootStateAccessPath(accessPath).asSource()
or
exists(string suffix, DataFlow::SourceNode base |
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(accessPath + "." + suffix).getAnImmediateUse()
+ succ = rootStateAccessPath(accessPath + "." + suffix).asSource()
)
)
or
@@ -901,7 +901,7 @@ module Redux {
reducer.isRootStateHandler() and
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(suffix).getAnImmediateUse()
+ succ = rootStateAccessPath(suffix).asSource()
)
}
@@ -916,7 +916,7 @@ module Redux {
*/
private DataFlow::ObjectLiteralNode getAManuallyDispatchedValue(string actionType) {
result.getAPropertyWrite("type").getRhs().mayHaveStringValue(actionType) and
- result = getADispatchedValueNode().getAValueReachingRhs()
+ result = getADispatchedValueNode().getAValueReachingSink()
}
/**
@@ -994,7 +994,7 @@ module Redux {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(API::CallNode call |
call = useSelector().getACall() and
- pred = call.getParameter(0).getReturn().getARhs() and
+ pred = call.getParameter(0).getReturn().asSink() and
succ = call
)
}
@@ -1046,19 +1046,19 @@ module Redux {
//
// const mapDispatchToProps = { foo }
//
- result = getMapDispatchToProps().getMember(name).getARhs()
+ result = getMapDispatchToProps().getMember(name).asSink()
or
//
// const mapDispatchToProps = dispatch => ( { foo } )
//
- result = getMapDispatchToProps().getReturn().getMember(name).getARhs()
+ result = getMapDispatchToProps().getReturn().getMember(name).asSink()
or
// Explicitly bound by bindActionCreators:
//
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
//
exists(BindActionCreatorsCall bind |
- bind.flowsTo(getMapDispatchToProps().getReturn().getARhs()) and
+ bind.flowsTo(getMapDispatchToProps().getReturn().asSink()) and
result = bind.getOptionArgument(0, name)
)
}
@@ -1096,9 +1096,7 @@ module Redux {
private class HeuristicConnectEntryPoint extends API::EntryPoint {
HeuristicConnectEntryPoint() { this = "react-redux-connect" }
- override DataFlow::Node getARhs() { none() }
-
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
exists(DataFlow::CallNode call |
call.getAnArgument().asExpr().(Identifier).getName() =
["mapStateToProps", "mapDispatchToProps"] and
@@ -1115,12 +1113,12 @@ module Redux {
override API::Node getMapStateToProps() {
result = getAParameter() and
- result.getARhs().asExpr().(Identifier).getName() = "mapStateToProps"
+ result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
}
override API::Node getMapDispatchToProps() {
result = getAParameter() and
- result.getARhs().asExpr().(Identifier).getName() = "mapDispatchToProps"
+ result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps"
}
}
@@ -1130,7 +1128,7 @@ module Redux {
private class StateToPropsStep extends StateStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ConnectCall call |
- pred = call.getMapStateToProps().getReturn().getARhs() and
+ pred = call.getMapStateToProps().getReturn().asSink() and
succ = call.getReactComponent().getADirectPropsAccess()
)
}
@@ -1205,7 +1203,7 @@ module Redux {
// Selector functions may be given as an array
exists(DataFlow::ArrayCreationNode array |
array.flowsTo(getArgument(0)) and
- result.getAUse() = array.getElement(i)
+ result.getAValueReachableFromSource() = array.getElement(i)
)
}
}
@@ -1221,13 +1219,13 @@ module Redux {
// Return value of `i`th callback flows to the `i`th parameter of the last callback.
exists(CreateSelectorCall call, int index |
call.getNumArgument() > 1 and
- pred = call.getSelectorFunction(index).getReturn().getARhs() and
- succ = call.getLastParameter().getParameter(index).getAnImmediateUse()
+ pred = call.getSelectorFunction(index).getReturn().asSink() and
+ succ = call.getLastParameter().getParameter(index).asSource()
)
or
// The result of the last callback is the final result
exists(CreateSelectorCall call |
- pred = call.getLastParameter().getReturn().getARhs() and
+ pred = call.getLastParameter().getReturn().asSink() and
succ = call
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
index 03c78c2561f..edd92614a2c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
@@ -9,7 +9,7 @@ module SQL {
abstract class SqlString extends Expr { }
private class SqlStringFromModel extends SqlString {
- SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").getARhs().asExpr() }
+ SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").asSink().asExpr() }
}
/**
@@ -109,7 +109,7 @@ private module MySql {
Credentials() {
exists(API::Node callee, string prop |
callee in [createConnection(), createPool()] and
- this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
+ this = callee.getParameter(0).getMember(prop).asSink().asExpr() and
(
prop = "user" and kind = "user name"
or
@@ -200,7 +200,7 @@ private module Postgres {
QueryString() {
this = any(QueryCall qc).getAQueryArgument().asExpr()
or
- this = API::moduleImport("pg-cursor").getParameter(0).getARhs().asExpr()
+ this = API::moduleImport("pg-cursor").getParameter(0).asSink().asExpr()
}
}
@@ -210,9 +210,9 @@ private module Postgres {
Credentials() {
exists(string prop |
- this = [newClient(), newPool()].getParameter(0).getMember(prop).getARhs().asExpr()
+ this = [newClient(), newPool()].getParameter(0).getMember(prop).asSink().asExpr()
or
- this = pgPromise().getParameter(0).getMember(prop).getARhs().asExpr()
+ this = pgPromise().getParameter(0).getMember(prop).asSink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -383,7 +383,7 @@ private module Sqlite {
/** A call to a Sqlite query method. */
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
QueryCall() {
- this = getAChainingQueryCall().getAnImmediateUse()
+ this = getAChainingQueryCall().asSource()
or
this = database().getMember("prepare").getACall()
}
@@ -440,7 +440,8 @@ private module MsSql {
override TaggedTemplateExpr astNode;
QueryTemplateExpr() {
- mssql().getMember("query").getAUse() = DataFlow::valueNode(astNode.getTag())
+ mssql().getMember("query").getAValueReachableFromSource() =
+ DataFlow::valueNode(astNode.getTag())
}
override DataFlow::Node getAResult() {
@@ -494,7 +495,7 @@ private module MsSql {
or
callee = mssql().getMember("ConnectionPool")
) and
- this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
+ this = callee.getParameter(0).getMember(prop).asSink().asExpr() and
(
prop = "user" and kind = "user name"
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
index d5692c3d2c2..6f460a842ff 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
@@ -27,7 +27,7 @@ private module Snapdragon {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(string methodName, API::CallNode set, API::CallNode call, API::Node base |
// the handler, registered with a call to `.set`.
- set = getSetCall+(base.getMember(methodName + "r")).getAnImmediateUse() and
+ set = getSetCall+(base.getMember(methodName + "r")).asSource() and
// the snapdragon instance. The API is chaining, you can also use the instance directly.
base = API::moduleImport("snapdragon").getInstance() and
methodName = ["parse", "compile"] and
@@ -47,7 +47,7 @@ private module Snapdragon {
or
// for compiler handlers the input is the first parameter.
methodName = "compile" and
- succ = set.getParameter(1).getParameter(0).getAnImmediateUse()
+ succ = set.getParameter(1).getParameter(0).asSource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
index df761420e29..e48d674fa74 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
@@ -41,7 +41,7 @@ module SocketIO {
class ServerObject extends SocketIOObject {
API::Node node;
- ServerObject() { node = newServer() and this = node.getAnImmediateUse() }
+ ServerObject() { node = newServer() and this = node.asSource() }
/** Gets the Api node for this server. */
API::Node asApiNode() { result = node }
@@ -81,7 +81,7 @@ module SocketIO {
)
}
- override DataFlow::SourceNode ref() { result = this.server().getAUse() }
+ override DataFlow::SourceNode ref() { result = this.server().getAValueReachableFromSource() }
}
/** A data flow node that may produce (that is, create or return) a socket.io server. */
@@ -119,7 +119,7 @@ module SocketIO {
API::Node node;
NamespaceBase() {
- this = node.getAnImmediateUse() and
+ this = node.asSource() and
exists(ServerObject srv |
// namespace lookup on `srv`
node = srv.asApiNode().getMember("sockets") and
@@ -158,7 +158,7 @@ module SocketIO {
)
}
- override DataFlow::SourceNode ref() { result = this.namespace().getAUse() }
+ override DataFlow::SourceNode ref() { result = this.namespace().getAValueReachableFromSource() }
}
/** A data flow node that may produce a namespace object. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index c1e6cb342f1..90adf7d7de6 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -233,7 +233,7 @@ module Templating {
/** Gets an API node that may flow to `succ` through a template instantiation. */
private API::Node getTemplateInput(DataFlow::SourceNode succ) {
exists(TemplateInstantiation inst, API::Node base, string name |
- base.getARhs() = inst.getTemplateParamsNode() and
+ base.asSink() = inst.getTemplateParamsNode() and
result = base.getMember(name) and
succ =
inst.getTemplateFile()
@@ -244,7 +244,7 @@ module Templating {
)
or
exists(TemplateInstantiation inst, string accessPath |
- result.getARhs() = inst.getTemplateParamForValue(accessPath) and
+ result.asSink() = inst.getTemplateParamForValue(accessPath) and
succ =
inst.getTemplateFile()
.getAnImportedFile*()
@@ -261,7 +261,7 @@ module Templating {
private class TemplateInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
- getTemplateInput(succ).getARhs() = pred
+ getTemplateInput(succ).asSink() = pred
}
}
@@ -321,8 +321,8 @@ module Templating {
result = this.getStringValue()
or
exists(API::Node node |
- this = node.getARhs() and
- result = node.getAValueReachingRhs().getStringValue()
+ this = node.asSink() and
+ result = node.getAValueReachingSink().getStringValue()
)
}
@@ -657,11 +657,9 @@ module Templating {
private class IncludeFunctionAsEntryPoint extends API::EntryPoint {
IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
result = any(TemplatePlaceholderTag tag).getInnerTopLevel().getAVariableUse("include")
}
-
- override DataFlow::Node getARhs() { none() }
}
/**
@@ -718,7 +716,7 @@ module Templating {
override TemplateSyntax getTemplateSyntax() { result.getAPackageName() = engine }
override DataFlow::SourceNode getOutput() {
- result = this.getParameter([1, 2]).getParameter(1).getAnImmediateUse()
+ result = this.getParameter([1, 2]).getParameter(1).asSource()
or
not exists(this.getParameter([1, 2]).getParameter(1)) and
result = this
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
index 1724e1174aa..29c100234bf 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
@@ -21,7 +21,7 @@ module ParseTorrent {
node = mod().getReturn() or
node = mod().getMember("remote").getParameter(1).getParameter(1)
) and
- this = node.getAnImmediateUse()
+ this = node.asSource()
}
/** Gets the API node for this torrent object. */
@@ -29,7 +29,9 @@ module ParseTorrent {
}
/** Gets a data flow node referring to a parsed torrent. */
- DataFlow::SourceNode parsedTorrentRef() { result = any(ParsedTorrent t).asApiNode().getAUse() }
+ DataFlow::SourceNode parsedTorrentRef() {
+ result = any(ParsedTorrent t).asApiNode().getAValueReachableFromSource()
+ }
/**
* An access to user-controlled torrent information.
@@ -38,7 +40,7 @@ module ParseTorrent {
UserControlledTorrentInfo() {
exists(API::Node read |
read = any(ParsedTorrent t).asApiNode().getAMember() and
- this = read.getAnImmediateUse()
+ this = read.asSource()
|
exists(string prop |
not (
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
index 8335600f9db..b1b2cc6cf0a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
@@ -14,9 +14,7 @@ module TrustedTypes {
private class TrustedTypesEntry extends API::EntryPoint {
TrustedTypesEntry() { this = "TrustedTypesEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("trustedTypes") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("trustedTypes") }
}
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getANode() }
@@ -38,7 +36,7 @@ module TrustedTypes {
private class PolicyInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(PolicyCreation policy, string method |
- pred = policy.getReturn().getMember(method).getParameter(0).getARhs() and
+ pred = policy.getReturn().getMember(method).getParameter(0).asSink() and
succ = policy.getPolicyCallback(method).getParameter(0)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
index 6551ef469e0..492139b3641 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
@@ -190,7 +190,7 @@ module Querystringify {
* Gets a data flow source node for member `name` of the querystringify library.
*/
DataFlow::SourceNode querystringifyMember(string name) {
- result = querystringify().getMember(name).getAnImmediateUse()
+ result = querystringify().getMember(name).asSource()
}
/** Gets an API node referring to the `querystringify` module. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index d32db710fa8..95a372025e2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -9,9 +9,7 @@ module Vue {
private class GlobalVueEntryPoint extends API::EntryPoint {
GlobalVueEntryPoint() { this = "VueEntryPoint" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("Vue") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Vue") }
}
/**
@@ -22,9 +20,7 @@ module Vue {
private class VueExportEntryPoint extends API::EntryPoint {
VueExportEntryPoint() { this = "VueExportEntryPoint" }
- override DataFlow::SourceNode getAUse() { none() }
-
- override DataFlow::Node getARhs() {
+ override DataFlow::Node getASink() {
result = any(SingleFileComponent c).getModule().getDefaultOrBulkExport()
}
}
@@ -41,7 +37,7 @@ module Vue {
/**
* Gets a reference to the 'Vue' object.
*/
- DataFlow::SourceNode vue() { result = vueLibrary().getAnImmediateUse() }
+ DataFlow::SourceNode vue() { result = vueLibrary().asSource() }
/** Gets an API node referring to a component or `Vue`. */
private API::Node component() {
@@ -176,8 +172,8 @@ module Vue {
/** Gets a component which is extended by this one. */
Component getABaseComponent() {
- result.getComponentRef().getAUse() =
- getOwnOptions().getMember(["extends", "mixins"]).getARhs()
+ result.getComponentRef().getAValueReachableFromSource() =
+ getOwnOptions().getMember(["extends", "mixins"]).asSink()
}
/**
@@ -195,12 +191,12 @@ module Vue {
}
/**
- * DEPRECATED. Use `getOwnOptions().getARhs()`.
+ * DEPRECATED. Use `getOwnOptions().getASink()`.
*
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
* or the default export of a single-file component.
*/
- deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().getARhs() }
+ deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().asSink() }
/**
* Gets the class implementing this Vue component, if any.
@@ -208,19 +204,19 @@ module Vue {
* Specifically, this is a class annotated with `@Component` which flows to the options
* object of this Vue component.
*/
- ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingRhs() }
+ ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingSink() }
/**
* Gets the node for option `name` for this component, not including
* those from extended objects and mixins.
*/
- DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).getARhs() }
+ DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).asSink() }
/**
* Gets the node for option `name` for this component, including those from
* extended objects and mixins.
*/
- DataFlow::Node getOption(string name) { result = getOptions().getMember(name).getARhs() }
+ DataFlow::Node getOption(string name) { result = getOptions().getMember(name).asSink() }
/**
* Gets a source node flowing into the option `name` of this component, including those from
@@ -228,7 +224,7 @@ module Vue {
*/
pragma[nomagic]
DataFlow::SourceNode getOptionSource(string name) {
- result = getOptions().getMember(name).getAValueReachingRhs()
+ result = getOptions().getMember(name).getAValueReachingSink()
}
/**
@@ -289,7 +285,7 @@ module Vue {
DataFlow::FunctionNode getWatchHandler(string propName) {
exists(API::Node propWatch |
propWatch = getOptions().getMember("watch").getMember(propName) and
- result = [propWatch, propWatch.getMember("handler")].getAValueReachingRhs()
+ result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink()
)
}
@@ -322,16 +318,16 @@ module Vue {
* Gets a node for a function that will be invoked with `this` bound to this component.
*/
DataFlow::FunctionNode getABoundFunction() {
- result = getOptions().getAMember+().getAValueReachingRhs()
+ result = getOptions().getAMember+().getAValueReachingSink()
or
result = getAsClassComponent().getAnInstanceMember()
}
/** Gets an API node referring to an instance of this component. */
- API::Node getInstance() { result.getAnImmediateUse() = getABoundFunction().getReceiver() }
+ API::Node getInstance() { result.asSource() = getABoundFunction().getReceiver() }
/** Gets a data flow node referring to an instance of this component. */
- DataFlow::SourceNode getAnInstanceRef() { result = getInstance().getAnImmediateUse() }
+ DataFlow::SourceNode getAnInstanceRef() { result = getInstance().asSource() }
pragma[noinline]
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
@@ -484,14 +480,12 @@ module Vue {
private class VueFileImportEntryPoint extends API::EntryPoint {
VueFileImportEntryPoint() { this = "VueFileImportEntryPoint" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
exists(Import imprt |
imprt.getImportedPath().resolve() instanceof VueFile and
result = imprt.getImportedModuleNode()
)
}
-
- override DataFlow::Node getARhs() { none() }
}
/**
@@ -533,13 +527,13 @@ module Vue {
// of the .vue file.
exists(Import imprt |
imprt.getImportedPath().resolve() = file and
- result.getAnImmediateUse() = imprt.getImportedModuleNode()
+ result.asSource() = imprt.getImportedModuleNode()
)
}
override API::Node getOwnOptions() {
// Use the entry point generated by `VueExportEntryPoint`
- result.getARhs() = getModule().getDefaultOrBulkExport()
+ result.asSink() = getModule().getDefaultOrBulkExport()
}
override string toString() { result = file.toString() }
@@ -695,7 +689,7 @@ module Vue {
t.start() and
(
exists(API::Node router | router = API::moduleImport("vue-router") |
- result = router.getInstance().getMember("currentRoute").getAnImmediateUse()
+ result = router.getInstance().getMember("currentRoute").asSource()
or
result =
router
@@ -703,17 +697,12 @@ module Vue {
.getMember(["beforeEach", "beforeResolve", "afterEach"])
.getParameter(0)
.getParameter([0, 1])
- .getAnImmediateUse()
+ .asSource()
or
- result =
- router
- .getParameter(0)
- .getMember("scrollBehavior")
- .getParameter([0, 1])
- .getAnImmediateUse()
+ result = router.getParameter(0).getMember("scrollBehavior").getParameter([0, 1]).asSource()
)
or
- result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getAnImmediateUse()
+ result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).asSource()
or
exists(Component c |
result = c.getABoundFunction().getAFunctionValue().getReceiver().getAPropertyRead("$route")
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
index 8d062a447aa..71132fb531d 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
@@ -75,7 +75,7 @@ module Vuex {
or
exists(API::CallNode call |
call = vuex().getMember("createNamespacedHelpers").getACall() and
- namespace = call.getParameter(0).getAValueReachingRhs().getStringValue() + "/" and
+ namespace = call.getParameter(0).getAValueReachingSink().getStringValue() + "/" and
this = call.getReturn().getMember(helperName).getACall()
)
)
@@ -88,7 +88,8 @@ module Vuex {
pragma[noinline]
string getNamespace() {
getNumArgument() = 2 and
- result = appendToNamespace(namespace, getParameter(0).getAValueReachingRhs().getStringValue())
+ result =
+ appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
or
getNumArgument() = 1 and
result = namespace
@@ -99,28 +100,28 @@ module Vuex {
*/
predicate hasMapping(string localName, string storeName) {
// mapGetters('foo')
- getLastParameter().getAValueReachingRhs().getStringValue() = localName and
+ getLastParameter().getAValueReachingSink().getStringValue() = localName and
storeName = getNamespace() + localName
or
// mapGetters(['foo', 'bar'])
- getLastParameter().getUnknownMember().getAValueReachingRhs().getStringValue() = localName and
+ getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() = localName and
storeName = getNamespace() + localName
or
// mapGetters({foo: 'bar'})
storeName =
getNamespace() +
- getLastParameter().getMember(localName).getAValueReachingRhs().getStringValue() and
+ getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
localName != "*" // ignore special API graph member named "*"
}
/** Gets the Vue component in which the generated functions are installed. */
Vue::Component getVueComponent() {
exists(DataFlow::ObjectLiteralNode obj |
- obj.getASpreadProperty() = getReturn().getAUse() and
- result.getOwnOptions().getAMember().getARhs() = obj
+ obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
+ result.getOwnOptions().getAMember().asSink() = obj
)
or
- result.getOwnOptions().getAMember().getARhs() = this
+ result.getOwnOptions().getAMember().asSink() = this
}
}
@@ -146,7 +147,7 @@ module Vuex {
/** Gets a value that is returned by a getter registered with the given name. */
private DataFlow::Node getterPred(string name) {
exists(string prefix, string prop |
- result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().getARhs() and
+ result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().asSink() and
name = prefix + prop
)
}
@@ -154,12 +155,12 @@ module Vuex {
/** Gets a property access that may receive the produced by a getter of the given name. */
private DataFlow::Node getterSucc(string name) {
exists(string prefix, string prop |
- result = storeRef(prefix).getMember("getters").getMember(prop).getAnImmediateUse() and
+ result = storeRef(prefix).getMember("getters").getMember(prop).asSource() and
prop != "*" and
name = prefix + prop
)
or
- result = getAMappedAccess("mapGetters", name).getAnImmediateUse()
+ result = getAMappedAccess("mapGetters", name).asSource()
}
/** Holds if `pred -> succ` is a step from a getter function to a relevant property access. */
@@ -212,19 +213,19 @@ module Vuex {
commitCall = commitLikeFunctionRef(kind, prefix).getACall()
|
// commit('name', payload)
- name = prefix + commitCall.getParameter(0).getAValueReachingRhs().getStringValue() and
+ name = prefix + commitCall.getParameter(0).getAValueReachingSink().getStringValue() and
result = commitCall.getArgument(1)
or
// commit({type: 'name', ......})
name =
prefix +
- commitCall.getParameter(0).getMember("type").getAValueReachingRhs().getStringValue() and
+ commitCall.getParameter(0).getMember("type").getAValueReachingSink().getStringValue() and
result = commitCall.getArgument(0)
)
or
// this.name(payload)
// methods: {...mapMutations(['name'])} }
- result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).getARhs()
+ result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).asSink()
}
/** Gets a node that refers the payload of a committed mutation with the given `name.` */
@@ -238,7 +239,7 @@ module Vuex {
.getMember(getStorePropForCommitKind(kind))
.getMember(prop)
.getParameter(1)
- .getAnImmediateUse() and
+ .asSource() and
prop != "*" and
name = prefix + prop
)
@@ -293,19 +294,17 @@ module Vuex {
/** Gets a value that flows into the given access path of the state. */
DataFlow::Node stateMutationPred(string path) {
- result = stateRefByAccessPath(path).getARhs()
+ result = stateRefByAccessPath(path).asSink()
or
exists(ExtendCall call, string base, string prop |
- call.getDestinationOperand() = stateRefByAccessPath(base).getAUse() and
+ call.getDestinationOperand() = stateRefByAccessPath(base).getAValueReachableFromSource() and
result = call.getASourceOperand().getALocalSource().getAPropertyWrite(prop).getRhs() and
path = appendToNamespace(base, prop)
)
}
/** Gets a value that refers to the given access path of the state. */
- DataFlow::Node stateMutationSucc(string path) {
- result = stateRefByAccessPath(path).getAnImmediateUse()
- }
+ DataFlow::Node stateMutationSucc(string path) { result = stateRefByAccessPath(path).asSource() }
/** Holds if `pred -> succ` is a step from state mutation to state access. */
predicate stateMutationStep(DataFlow::Node pred, DataFlow::Node succ) {
@@ -325,7 +324,7 @@ module Vuex {
exists(MapHelperCall call |
call.getHelperName() = "mapState" and
component = call.getVueComponent() and
- result = call.getLastParameter().getMember(name).getReturn().getARhs()
+ result = call.getLastParameter().getMember(name).getReturn().asSink()
)
}
@@ -336,7 +335,7 @@ module Vuex {
predicate mapStateHelperStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Vue::Component component, string name |
pred = mapStateHelperPred(component, name) and
- succ = pragma[only_bind_out](component).getInstance().getMember(name).getAnImmediateUse()
+ succ = pragma[only_bind_out](component).getInstance().getMember(name).asSource()
)
}
@@ -378,7 +377,7 @@ module Vuex {
/** Gets a package that can be considered an entry point for a Vuex app. */
private PackageJson entryPointPackage() {
- result = getPackageJson(storeRef().getAnImmediateUse().getFile())
+ result = getPackageJson(storeRef().asSource().getFile())
or
// Any package that imports a store-creating package is considered a potential entry point.
packageDependsOn(result, entryPointPackage())
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
index 41cecb36941..355ee485246 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
@@ -100,7 +100,7 @@ module XML {
}
override DataFlow::Node getAResult() {
- result = [doc(), element(), attr()].getAnImmediateUse()
+ result = [doc(), element(), attr()].asSource()
or
result = element().getMember(["name", "text"]).getACall()
or
@@ -282,11 +282,7 @@ module XML {
override DataFlow::Node getAResult() {
result =
- parser
- .getReturn()
- .getMember(any(string s | s.matches("on%")))
- .getAParameter()
- .getAnImmediateUse()
+ parser.getReturn().getMember(any(string s | s.matches("on%"))).getAParameter().asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
index f8b2118a55f..bbed827c3e5 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
@@ -26,7 +26,7 @@ import Shared::ModelOutput as ModelOutput
* A remote flow source originating from a CSV source row.
*/
private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
- RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").getAnImmediateUse() }
+ RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").asSource() }
override string getSourceType() { result = "Remote flow" }
}
@@ -37,8 +37,8 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(API::Node predNode, API::Node succNode |
Specific::summaryStep(predNode, succNode, kind) and
- pred = predNode.getARhs() and
- succ = succNode.getAnImmediateUse()
+ pred = predNode.asSink() and
+ succ = succNode.asSource()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll
index 127d9ca5122..69563a3eab4 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll
@@ -299,7 +299,7 @@ private class AccessPathRange extends AccessPath::Range {
bindingset[token]
API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
// API graphs use the same label for arguments and parameters. An edge originating from a
- // use-node represents be an argument, and an edge originating from a def-node represents a parameter.
+ // use-node represents an argument, and an edge originating from a def-node represents a parameter.
// We just map both to the same thing.
token.getName() = ["Argument", "Parameter"] and
result = node.getParameter(AccessPath::parseIntUnbounded(token.getAnArgument()))
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index a5e366a671f..861a44a2cfc 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -61,9 +61,7 @@ private class GlobalApiEntryPoint extends API::EntryPoint {
this = "GlobalApiEntryPoint:" + global
}
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(global) }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(global) }
/** Gets the name of the global variable. */
string getGlobal() { result = global }
@@ -151,7 +149,7 @@ API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken toke
or
token.getName() = "Argument" and
token.getAnArgument() = "this" and
- result.getARhs() = node.(DataFlow::CallNode).getReceiver()
+ result.asSink() = node.(DataFlow::CallNode).getReceiver()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
index 35b1ac83e2d..40c86ed4855 100644
--- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
+++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
@@ -58,7 +58,7 @@ class RemoteServerResponse extends HeuristicSource, RemoteFlowSource {
*/
private class RemoteFlowSourceFromDBAccess extends RemoteFlowSource, HeuristicSource {
RemoteFlowSourceFromDBAccess() {
- this = ModelOutput::getASourceNode("database-access-result").getAUse() or
+ this = ModelOutput::getASourceNode("database-access-result").getAValueReachableFromSource() or
exists(DatabaseAccess dba | this = dba.getAResult())
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
index 93c9fa63a59..b23f52d7c22 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
@@ -49,7 +49,7 @@ module DomBasedXss {
or
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
exists(DataFlow::NewNode instance |
- instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
+ instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().asSource() and
this = instance.getArgument(0) and
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
index 30ae50c2382..2418962ef65 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
@@ -61,7 +61,7 @@ module ExceptionXss {
*/
private class JsonSchemaValidationError extends Source {
JsonSchemaValidationError() {
- this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
+ this = any(JsonSchema::Ajv::Instance i).getAValidationError().asSource()
or
this = any(JsonSchema::Joi::JoiValidationErrorRead r).getAValidationResultAccess(_)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
index a061fd5bc6f..fb663a755ed 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
@@ -48,7 +48,7 @@ module ExternalApiUsedWithUntrustedData {
}
/** Holds if `node` corresponds to a deep object argument. */
- private predicate isDeepObjectSink(API::Node node) { node.getARhs() instanceof DeepObjectSink }
+ private predicate isDeepObjectSink(API::Node node) { node.asSink() instanceof DeepObjectSink }
/**
* A sanitizer for data flowing to an external API.
@@ -165,9 +165,9 @@ module ExternalApiUsedWithUntrustedData {
not param = base.getReceiver()
|
result = param and
- name = param.getAnImmediateUse().asExpr().(Parameter).getName()
+ name = param.asSource().asExpr().(Parameter).getName()
or
- param.getAnImmediateUse().asExpr() instanceof DestructuringPattern and
+ param.asSource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
index a410bda46b5..108ce5d8e62 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
@@ -74,7 +74,7 @@ module IndirectCommandInjection {
].getMember("parse").getACall()
or
// `require('commander').myCmdArgumentName`
- this = commander().getAMember().getAnImmediateUse()
+ this = commander().getAMember().asSource()
or
// `require('commander').opt()` => `{a: ..., b: ...}`
this = commander().getMember("opts").getACall()
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
index fc30c91018a..f1a27697725 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
@@ -152,9 +152,7 @@ abstract class RateLimitingMiddleware extends DataFlow::SourceNode {
* A rate limiter constructed using the `express-rate-limit` package.
*/
class ExpressRateLimit extends RateLimitingMiddleware {
- ExpressRateLimit() {
- this = API::moduleImport("express-rate-limit").getReturn().getAnImmediateUse()
- }
+ ExpressRateLimit() { this = API::moduleImport("express-rate-limit").getReturn().asSource() }
}
/**
@@ -162,7 +160,7 @@ class ExpressRateLimit extends RateLimitingMiddleware {
*/
class BruteForceRateLimit extends RateLimitingMiddleware {
BruteForceRateLimit() {
- this = API::moduleImport("express-brute").getInstance().getMember("prevent").getAnImmediateUse()
+ this = API::moduleImport("express-brute").getInstance().getMember("prevent").asSource()
}
}
@@ -174,7 +172,7 @@ class BruteForceRateLimit extends RateLimitingMiddleware {
*/
class RouteHandlerLimitedByExpressLimiter extends RateLimitingMiddleware {
RouteHandlerLimitedByExpressLimiter() {
- this = API::moduleImport("express-limiter").getReturn().getReturn().getAnImmediateUse()
+ this = API::moduleImport("express-limiter").getReturn().getReturn().asSource()
}
override Routing::Node getRoutingNode() {
@@ -211,7 +209,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
- request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().getARhs())
+ request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().asSink())
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
index ff026f3a3a4..bb60b5bc23e 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
@@ -164,9 +164,7 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
string getName() { result = name }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(name) }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(name) }
}
/**
@@ -175,7 +173,7 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
private class ExternalRemoteFlowSource extends RemoteFlowSource {
RemoteFlowSourceAccessPath ap;
- ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().getAnImmediateUse() }
+ ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().asSource() }
override string getSourceType() { result = ap.getSourceType() }
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll
index 695876ac90f..8307c1f6f93 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll
@@ -78,14 +78,8 @@ module ResourceExhaustion {
exists(DataFlow::SourceNode clazz, DataFlow::InvokeNode invk, int index |
clazz = DataFlow::globalVarRef("Buffer") and this = invk.getArgument(index)
|
- exists(string name |
- invk = clazz.getAMemberCall(name) and
- (
- name = "from" and index = 2 // the length argument
- or
- name = ["alloc", "allocUnsafe", "allocUnsafeSlow"] and index = 0 // the buffer size
- )
- )
+ invk = clazz.getAMemberCall(["alloc", "allocUnsafe", "allocUnsafeSlow"]) and
+ index = 0 // the buffer size
or
invk = clazz.getAnInvocation() and
(
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
index e3bf02362a4..42ffe2ea3c3 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
@@ -51,7 +51,7 @@ module SqlInjection {
this = any(LdapJS::ClientCall call).getArgument(0)
or
// A search options object, which contains a filter and a baseDN.
- this = any(LdapJS::SearchOptions opt).getARhs()
+ this = any(LdapJS::SearchOptions opt).asSink()
or
// A call to "parseDN", which parses a DN from a string.
this = LdapJS::ldapjs().getMember("parseDN").getACall().getArgument(0)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
index c094d82163c..03b1211326a 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
@@ -681,7 +681,7 @@ module TaintedPath {
.getMember(["pdf", "screenshot"])
.getParameter(0)
.getMember("path")
- .getARhs()
+ .asSink()
}
}
@@ -702,7 +702,7 @@ module TaintedPath {
.getACall()
.getParameter(1)
.getMember("config")
- .getARhs()
+ .asSink()
}
}
@@ -716,7 +716,7 @@ module TaintedPath {
.getMember(["readPackageAsync", "readPackageSync"])
.getParameter(0)
.getMember("cwd")
- .getARhs()
+ .asSink()
}
}
@@ -726,8 +726,8 @@ module TaintedPath {
private class ShellCwdSink extends TaintedPath::Sink {
ShellCwdSink() {
exists(SystemCommandExecution sys, API::Node opts |
- opts.getARhs() = sys.getOptionsArg() and // assuming that an API::Node exists here.
- this = opts.getMember("cwd").getARhs()
+ opts.asSink() = sys.getOptionsArg() and // assuming that an API::Node exists here.
+ this = opts.getMember("cwd").asSink()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
index da6b698d97f..8e24b3e36d8 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
@@ -27,4 +27,30 @@ class Configuration extends DataFlow::Configuration {
}
override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier }
+
+ override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) {
+ guard instanceof TypeOfTestBarrier or
+ guard instanceof IsArrayBarrier
+ }
+}
+
+private class TypeOfTestBarrier extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
+ override EqualityTest astNode;
+
+ TypeOfTestBarrier() { TaintTracking::isTypeofGuard(astNode, _, _) }
+
+ override predicate blocks(boolean outcome, Expr e) {
+ if TaintTracking::isTypeofGuard(astNode, e, ["string", "object"])
+ then outcome = [true, false] // separation between string/array removes type confusion in both branches
+ else outcome = astNode.getPolarity() // block flow to branch where value is neither string nor array
+ }
+}
+
+private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallNode {
+ IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray").getACall() }
+
+ override predicate blocks(boolean outcome, Expr e) {
+ e = getArgument(0).asExpr() and
+ outcome = [true, false] // separation between string/array removes type confusion in both branches
+ }
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index b869b028902..3f0f569eff6 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -208,8 +208,7 @@ module XssThroughDom {
exists(API::Node useForm |
useForm = API::moduleImport("react-hook-form").getMember("useForm").getReturn()
|
- this =
- useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getAnImmediateUse()
+ this = useForm.getMember("handleSubmit").getParameter(0).getParameter(0).asSource()
or
this = useForm.getMember("getValues").getACall()
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
index 3c4c5f66b75..1cb58609d13 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
@@ -103,7 +103,7 @@ module ZipSlip {
class JSZipFilesSource extends Source instanceof DynamicPropertyAccess::EnumeratedPropName {
JSZipFilesSource() {
super.getSourceObject() =
- API::moduleImport("jszip").getInstance().getMember("files").getAnImmediateUse()
+ API::moduleImport("jszip").getInstance().getMember("files").asSource()
}
}
@@ -116,7 +116,7 @@ module ZipSlip {
.getMember(["forEach", "filter"])
.getParameter(0)
.getParameter(0)
- .getAnImmediateUse()
+ .asSource()
}
}
diff --git a/javascript/ql/src/Declarations/UnusedProperty.ql b/javascript/ql/src/Declarations/UnusedProperty.ql
index 19d43a09db2..1a8f9ee291f 100644
--- a/javascript/ql/src/Declarations/UnusedProperty.ql
+++ b/javascript/ql/src/Declarations/UnusedProperty.ql
@@ -27,6 +27,8 @@ predicate hasUnknownPropertyRead(LocalObject obj) {
or
exists(obj.getAPropertyRead("hasOwnProperty"))
or
+ obj.flowsTo(DataFlow::globalVarRef("Object").getAMemberCall("hasOwn").getArgument(0))
+ or
exists(obj.getAPropertyRead("propertyIsEnumerable"))
}
diff --git a/javascript/ql/src/Performance/PolynomialReDoS.qhelp b/javascript/ql/src/Performance/PolynomialReDoS.qhelp
index 78746df38ad..210a4a8a84b 100644
--- a/javascript/ql/src/Performance/PolynomialReDoS.qhelp
+++ b/javascript/ql/src/Performance/PolynomialReDoS.qhelp
@@ -71,7 +71,7 @@
- ^0\.\d+E?\d+$ // BAD
+ /^0\.\d+E?\d+$/.test(str) // BAD
diff --git a/javascript/ql/src/Security/CWE-020/MissingOriginCheck.ql b/javascript/ql/src/Security/CWE-020/MissingOriginCheck.ql
index 543d3996abb..107f1c9a12c 100644
--- a/javascript/ql/src/Security/CWE-020/MissingOriginCheck.ql
+++ b/javascript/ql/src/Security/CWE-020/MissingOriginCheck.ql
@@ -9,6 +9,7 @@
* @tags correctness
* security
* external/cwe/cwe-020
+ * external/cwe/cwe-940
*/
import javascript
diff --git a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
index 42861fcb9be..7fd76a635ec 100644
--- a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
+++ b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
@@ -45,7 +45,7 @@ where
or
// the same thing, but with API-nodes if they happen to be available
exists(API::Node tlsInvk | tlsInvk.getAnInvocation() = tlsInvocation() |
- disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").getARhs()
+ disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").asSink()
)
) and
disable.getRhs().(AnalyzedNode).getTheBooleanValue() = false
diff --git a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
index 52617ce675d..6240615a6e7 100644
--- a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
+++ b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
@@ -143,7 +143,7 @@ API::CallNode passportAuthenticateCall() {
*/
API::CallNode nonSessionBasedAuthMiddleware() {
result = passportAuthenticateCall() and
- result.getParameter(1).getMember("session").getARhs().mayHaveBooleanValue(false)
+ result.getParameter(1).getMember("session").asSink().mayHaveBooleanValue(false)
}
/**
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
index 2fb9cece66d..9e5b873f663 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
@@ -339,19 +339,16 @@ class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod
* but the destination object generally doesn't. It is therefore only a sanitizer when
* used on the destination object.
*/
-class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode {
+class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPropertyCall {
HasOwnPropertyGuard() {
- // Make sure we handle reflective calls since libraries love to do that.
- getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() = "hasOwnProperty" and
- exists(getReceiver()) and
// Try to avoid `src.hasOwnProperty` by requiring that the receiver
// does not locally have its properties enumerated. Typically there is no
// reason to enumerate the properties of the destination object.
- not arePropertiesEnumerated(getReceiver().getALocalSource())
+ not arePropertiesEnumerated(super.getObject().getALocalSource())
}
override predicate blocks(boolean outcome, Expr e) {
- e = getArgument(0).asExpr() and outcome = true
+ e = super.getProperty().asExpr() and outcome = true
}
}
diff --git a/javascript/ql/src/change-notes/2022-05-24-resource-exhaustion-no-buffer.from.md b/javascript/ql/src/change-notes/2022-05-24-resource-exhaustion-no-buffer.from.md
new file mode 100644
index 00000000000..8dadbdb4c93
--- /dev/null
+++ b/javascript/ql/src/change-notes/2022-05-24-resource-exhaustion-no-buffer.from.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+* The `js/resource-exhaustion` query no longer treats the 3-argument version of `Buffer.from` as a sink,
+ since it does not allocate a new buffer.
diff --git a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
index fcb98dc57af..4f07f9be7fe 100644
--- a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
+++ b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
@@ -12,4 +12,4 @@
import javascript
import meta.MetaMetrics
-select projectRoot(), count(any(API::Node nd).getARhs())
+select projectRoot(), count(any(API::Node nd).asSink())
diff --git a/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql b/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
index 446df101364..8f6629cc624 100644
--- a/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
+++ b/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
@@ -11,4 +11,4 @@
import javascript
import meta.MetaMetrics
-select projectRoot(), count(any(API::Node nd).getAUse())
+select projectRoot(), count(any(API::Node nd).getAValueReachableFromSource())
diff --git a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
index a81c0d03ae9..c65f2b7ad81 100644
--- a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
+++ b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
@@ -21,10 +21,10 @@ import javascript
private DataFlow::Node getNode(API::Node nd, string kind) {
kind = "def" and
- result = nd.getARhs()
+ result = nd.asSink()
or
kind = "use" and
- result = nd.getAUse()
+ result = nd.getAValueReachableFromSource()
}
private string getLoc(DataFlow::Node nd) {
diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.ql b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
index cbea83fa4be..8f0ea4bfc8b 100644
--- a/javascript/ql/test/ApiGraphs/call-nodes/test.ql
+++ b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
@@ -3,9 +3,9 @@ import javascript
class FooCall extends API::CallNode {
FooCall() { this = API::moduleImport("mylibrary").getMember("foo").getACall() }
- DataFlow::Node getFirst() { result = getParameter(0).getMember("value").getARhs() }
+ DataFlow::Node getFirst() { result = getParameter(0).getMember("value").asSink() }
- DataFlow::Node getSecond() { result = getParameter(1).getMember("value").getARhs() }
+ DataFlow::Node getSecond() { result = getParameter(1).getMember("value").asSink() }
}
query predicate values(FooCall call, int first, int second) {
diff --git a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
index fb8a943f2ca..3502c0ea556 100644
--- a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
+++ b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
@@ -1,9 +1,7 @@
class CustomEntryPoint extends API::EntryPoint {
CustomEntryPoint() { this = "CustomEntryPoint" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("CustomEntryPoint") }
-
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("CustomEntryPoint") }
}
import ApiGraphs.VerifyAssertions
diff --git a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
index 582385c802a..10c5133f9a8 100644
--- a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
+++ b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
@@ -1,4 +1,4 @@
import javascript
from string mod, string tp
-select mod, tp, API::Node::ofType(mod, tp).getAnImmediateUse()
+select mod, tp, API::Node::ofType(mod, tp).asSource()
diff --git a/javascript/ql/test/library-tests/Arrays/DataFlow.expected b/javascript/ql/test/library-tests/Arrays/DataFlow.expected
index fd98b66d4db..2f5179075cf 100644
--- a/javascript/ql/test/library-tests/Arrays/DataFlow.expected
+++ b/javascript/ql/test/library-tests/Arrays/DataFlow.expected
@@ -11,6 +11,7 @@
| arrays.js:2:16:2:23 | "source" | arrays.js:74:8:74:29 | arr.fin ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:77:8:77:35 | arrayFi ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:81:10:81:10 | x |
+| arrays.js:2:16:2:23 | "source" | arrays.js:84:8:84:17 | arr.at(-1) |
| arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e |
| arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() |
| arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() |
diff --git a/javascript/ql/test/library-tests/Arrays/arrays.js b/javascript/ql/test/library-tests/Arrays/arrays.js
index 9b445760f47..2dfb203cd54 100644
--- a/javascript/ql/test/library-tests/Arrays/arrays.js
+++ b/javascript/ql/test/library-tests/Arrays/arrays.js
@@ -80,4 +80,6 @@
for (const x of uniq(arr)) {
sink(x); // NOT OK
}
+
+ sink(arr.at(-1)); // NOT OK
});
diff --git a/javascript/ql/test/library-tests/Arrays/printAst.expected b/javascript/ql/test/library-tests/Arrays/printAst.expected
index 8364838f8bd..c6e097c770e 100644
--- a/javascript/ql/test/library-tests/Arrays/printAst.expected
+++ b/javascript/ql/test/library-tests/Arrays/printAst.expected
@@ -1,9 +1,9 @@
nodes
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | [ParExpr] (functi ... } }) |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.label | [ExprStmt] (functi ... } }); |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.order | 1 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | [FunctionExpr] functio ... K } } |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | [BlockStmt] { let ... K } } |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | [ParExpr] (functi ... T OK }) |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.label | [ExprStmt] (functi ... OK }); |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.order | 1 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | [FunctionExpr] functio ... OT OK } |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | [BlockStmt] { let ... OT OK } |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | [DeclStmt] let source = ... |
| arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | [VarDecl] source |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | [VariableDeclarator] source = "source" |
@@ -339,6 +339,17 @@ nodes
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | [CallExpr] sink(x) |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | semmle.label | [ExprStmt] sink(x); |
| arrays.js:81:10:81:10 | [VarRef] x | semmle.label | [VarRef] x |
+| arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | [VarRef] sink |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | [CallExpr] sink(arr.at(-1)) |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | [ExprStmt] sink(arr.at(-1)); |
+| arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | [VarRef] arr |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | [DotExpr] arr.at |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | [MethodCallExpr] arr.at(-1) |
+| arrays.js:84:12:84:13 | [Label] at | semmle.label | [Label] at |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | [UnaryExpr] -1 |
+| arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | [Literal] 1 |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
@@ -386,88 +397,90 @@ nodes
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
edges
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | 1 |
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.order | 1 |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | 1 |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.order | 1 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | 5 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.order | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | 1 |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.order | 1 |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | 1 |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.order | 1 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | 5 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.order | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | 39 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.order | 39 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | 1 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.order | 1 |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | 1 |
@@ -1052,6 +1065,22 @@ edges
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.order | 1 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | 0 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.order | 0 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | 1 |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.order | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.order | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.label | 2 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.order | 2 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | 0 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.order | 0 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | 1 |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.order | 1 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:8:12:8:17 | [VarRef] source | semmle.label | 0 |
@@ -1140,6 +1169,10 @@ edges
| file://:0:0:0:0 | (Arguments) | arrays.js:80:24:80:26 | [VarRef] arr | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:16:12:16:12 | [SimpleParameter] e | semmle.label | 0 |
diff --git a/javascript/ql/test/library-tests/Routing/test.ql b/javascript/ql/test/library-tests/Routing/test.ql
index aa89c7212d2..b427f710894 100644
--- a/javascript/ql/test/library-tests/Routing/test.ql
+++ b/javascript/ql/test/library-tests/Routing/test.ql
@@ -9,12 +9,12 @@ class Taint extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node node) {
node.(DataFlow::CallNode).getCalleeName() = "source"
or
- node = testInstance().getMember("getSource").getReturn().getAnImmediateUse()
+ node = testInstance().getMember("getSource").getReturn().asSource()
}
override predicate isSink(DataFlow::Node node) {
node = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- node = testInstance().getMember("getSink").getAParameter().getARhs()
+ node = testInstance().getMember("getSink").getAParameter().asSink()
}
}
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tests.expected b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
index 33f06a2ff23..3ee1223b87d 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tests.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
@@ -43,6 +43,10 @@ isLabeledBarrier
| ExampleConfiguration | tst.js:361:14:361:14 | v | taint |
| ExampleConfiguration | tst.js:371:14:371:16 | o.p | taint |
| ExampleConfiguration | tst.js:378:14:378:17 | o[p] | taint |
+| ExampleConfiguration | tst.js:392:14:392:14 | v | taint |
+| ExampleConfiguration | tst.js:394:14:394:16 | v.p | taint |
+| ExampleConfiguration | tst.js:396:14:396:18 | v.p.q | taint |
+| ExampleConfiguration | tst.js:402:14:402:14 | v | taint |
isSanitizer
| ExampleConfiguration | tst.js:176:18:176:18 | v |
sanitizingGuard
@@ -122,6 +126,12 @@ sanitizingGuard
| tst.js:370:9:370:29 | o.p == ... listed" | tst.js:370:16:370:29 | "white-listed" | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:11:377:14 | o[p] | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:19:377:32 | "white-listed" | true |
+| tst.js:391:9:391:27 | o.hasOwnProperty(v) | tst.js:391:26:391:26 | v | true |
+| tst.js:393:16:393:36 | o.hasOw ... ty(v.p) | tst.js:393:33:393:35 | v.p | true |
+| tst.js:395:16:395:38 | o.hasOw ... (v.p.q) | tst.js:395:33:395:37 | v.p.q | true |
+| tst.js:397:16:397:36 | o.hasOw ... ty(v.p) | tst.js:397:33:397:35 | v.p | true |
+| tst.js:399:16:399:41 | o.hasOw ... "p.q"]) | tst.js:399:33:399:40 | v["p.q"] | true |
+| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:33:401:33 | v | true |
taintedSink
| tst.js:2:13:2:20 | SOURCE() | tst.js:3:10:3:10 | v |
| tst.js:2:13:2:20 | SOURCE() | tst.js:8:14:8:14 | v |
@@ -186,3 +196,6 @@ taintedSink
| tst.js:367:13:367:20 | SOURCE() | tst.js:373:14:373:16 | o.p |
| tst.js:367:13:367:20 | SOURCE() | tst.js:380:14:380:17 | o[p] |
| tst.js:367:13:367:20 | SOURCE() | tst.js:382:14:382:17 | o[p] |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:389:10:389:14 | v.p.q |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:398:14:398:14 | v |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:400:14:400:18 | v.p.q |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js
index 265c5ac6210..20102605af1 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tst.js
+++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js
@@ -383,3 +383,22 @@ function constantComparisonSanitizer2() {
}
}
}
+
+function propertySanitization(o) {
+ var v = SOURCE();
+ SINK(v.p.q); // NOT OK
+
+ if (o.hasOwnProperty(v)) {
+ SINK(v); // OK
+ } else if (o.hasOwnProperty(v.p)) {
+ SINK(v.p); // OK
+ } else if (o.hasOwnProperty(v.p.q)) {
+ SINK(v.p.q); // OK
+ } else if (o.hasOwnProperty(v.p)) {
+ SINK(v); // NOT OK
+ } else if (o.hasOwnProperty(v["p.q"])) {
+ SINK(v.p.q); // NOT OK
+ } else if (Object.hasOwn(o, v)) {
+ SINK(v); // OK
+ }
+}
diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
index 12fdd69e80f..cd41461e4a8 100644
--- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
+++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
@@ -17,6 +17,7 @@ typeInferenceMismatch
| arrays.js:2:15:2:22 | source() | arrays.js:11:10:11:28 | union(["bla"], foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:14:10:14:18 | flat(foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:19:10:19:12 | res |
+| arrays.js:2:15:2:22 | source() | arrays.js:21:10:21:19 | foo.at(-1) |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:4:8:4:8 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:13:10:13:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:19:10:19:10 | x |
diff --git a/javascript/ql/test/library-tests/TaintTracking/arrays.js b/javascript/ql/test/library-tests/TaintTracking/arrays.js
index b99e2058d80..b9daf4943b3 100644
--- a/javascript/ql/test/library-tests/TaintTracking/arrays.js
+++ b/javascript/ql/test/library-tests/TaintTracking/arrays.js
@@ -17,4 +17,6 @@ function test() {
return prev + '' + current + '';
}, '');
sink(res); // NOT OK
+
+ sink(foo.at(-1)); // NOT OK
}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
index e50154887a2..9f4f6c6aba5 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
@@ -94,6 +94,11 @@ nodes
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
@@ -120,6 +125,17 @@ nodes
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
+| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
+| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
+| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
+| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
@@ -1128,17 +1144,314 @@ nodes
| tst.ts:293:7:293:23 | [MethodCallExpr] payload.toFixed() | semmle.label | [MethodCallExpr] payload.toFixed() |
| tst.ts:293:7:293:24 | [ExprStmt] payload.toFixed(); | semmle.label | [ExprStmt] payload.toFixed(); |
| tst.ts:293:15:293:21 | [Label] toFixed | semmle.label | [Label] toFixed |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.label | [DeclStmt] const key = ... |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.order | 61 |
+| tst.ts:298:7:298:9 | [VarDecl] key | semmle.label | [VarDecl] key |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | semmle.label | [VariableDeclarator] key = Symbol() |
+| tst.ts:298:13:298:18 | [VarRef] Symbol | semmle.label | [VarRef] Symbol |
+| tst.ts:298:13:298:20 | [CallExpr] Symbol() | semmle.label | [CallExpr] Symbol() |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.label | [DeclStmt] const numberOrString = ... |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.order | 62 |
+| tst.ts:300:7:300:20 | [VarDecl] numberOrString | semmle.label | [VarDecl] numberOrString |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | semmle.label | [VariableDeclarator] numberO ... "hello" |
+| tst.ts:300:24:300:27 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | semmle.label | [BinaryExpr] Math.random() < 0.5 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | semmle.label | [ConditionalExpr] Math.ra ... "hello" |
+| tst.ts:300:29:300:34 | [Label] random | semmle.label | [Label] random |
+| tst.ts:300:40:300:42 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tst.ts:300:46:300:47 | [Literal] 42 | semmle.label | [Literal] 42 |
+| tst.ts:300:51:300:57 | [Literal] "hello" | semmle.label | [Literal] "hello" |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.label | [DeclStmt] let obj = ... |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.order | 63 |
+| tst.ts:302:5:302:7 | [VarDecl] obj | semmle.label | [VarDecl] obj |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | semmle.label | [VariableDeclarator] obj = { ... ring, } |
+| tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | semmle.label | [ObjectExpr] { [ke ... ring, } |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | semmle.label | [Property] [key]: ... rString |
+| tst.ts:303:4:303:6 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:303:10:303:23 | [VarRef] numberOrString | semmle.label | [VarRef] numberOrString |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.label | [IfStmt] if (typ ... se(); } |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.order | 64 |
+| tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | semmle.label | [UnaryExpr] typeof obj[key] |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" |
+| tst.ts:306:12:306:14 | [VarRef] obj | semmle.label | [VarRef] obj |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
+| tst.ts:306:16:306:18 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:306:25:306:32 | [Literal] "string" | semmle.label | [Literal] "string" |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | semmle.label | [BlockStmt] { let ... se(); } |
+| tst.ts:307:3:307:21 | [DeclStmt] let str = ... | semmle.label | [DeclStmt] let str = ... |
+| tst.ts:307:7:307:9 | [VarDecl] str | semmle.label | [VarDecl] str |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | semmle.label | [VariableDeclarator] str = obj[key] |
+| tst.ts:307:13:307:15 | [VarRef] obj | semmle.label | [VarRef] obj |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
+| tst.ts:307:17:307:19 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:308:3:308:5 | [VarRef] str | semmle.label | [VarRef] str |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | semmle.label | [DotExpr] str.toUpperCase |
+| tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | semmle.label | [MethodCallExpr] str.toUpperCase() |
+| tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | semmle.label | [ExprStmt] str.toUpperCase(); |
+| tst.ts:308:7:308:17 | [Label] toUpperCase | semmle.label | [Label] toUpperCase |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.label | [FunctionDeclStmt] functio ... void {} |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.order | 65 |
+| tst.ts:313:10:313:10 | [VarDecl] f | semmle.label | [VarDecl] f |
+| tst.ts:313:12:313:12 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:313:12:313:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
+| tst.ts:313:15:313:17 | [SimpleParameter] arg | semmle.label | [SimpleParameter] arg |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | semmle.label | [InterfaceTypeExpr] { pro ... void } |
+| tst.ts:314:3:314:9 | [Label] produce | semmle.label | [Label] produce |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | semmle.label | [FieldDeclaration] produce ... ) => T, |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | semmle.label | [FunctionExpr] (n: string) => T |
+| tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | semmle.label | [FunctionTypeExpr] (n: string) => T |
+| tst.ts:314:13:314:13 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
+| tst.ts:314:16:314:21 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:314:27:314:27 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:315:3:315:9 | [Label] consume | semmle.label | [Label] consume |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | semmle.label | [FieldDeclaration] consume ... => void |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | semmle.label | [FunctionExpr] (x: T) => void |
+| tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | semmle.label | [FunctionTypeExpr] (x: T) => void |
+| tst.ts:315:13:315:13 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
+| tst.ts:315:16:315:16 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:315:22:315:25 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:316:4:316:7 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:316:9:316:10 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
+| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
+| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.order | 66 |
+| tst.ts:318:1:318:1 | [VarRef] f | semmle.label | [VarRef] f |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | semmle.label | [CallExpr] f({ p ... se() }) |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.label | [ExprStmt] f({ p ... e() }); |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.order | 67 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | semmle.label | [ObjectExpr] {produce: ...} |
+| tst.ts:319:3:319:9 | [Label] produce | semmle.label | [Label] produce |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | semmle.label | [Property] produce: n => n |
+| tst.ts:319:12:319:12 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | semmle.label | [ArrowFunctionExpr] n => n |
+| tst.ts:319:17:319:17 | [VarRef] n | semmle.label | [VarRef] n |
+| tst.ts:320:3:320:9 | [Label] consume | semmle.label | [Label] consume |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | semmle.label | [Property] consume ... rCase() |
+| tst.ts:320:12:320:12 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | semmle.label | [ArrowFunctionExpr] x => x.toLowerCase() |
+| tst.ts:320:17:320:17 | [VarRef] x | semmle.label | [VarRef] x |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | semmle.label | [DotExpr] x.toLowerCase |
+| tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | semmle.label | [MethodCallExpr] x.toLowerCase() |
+| tst.ts:320:19:320:29 | [Label] toLowerCase | semmle.label | [Label] toLowerCase |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.label | [DeclStmt] const ErrorMap = ... |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.order | 68 |
+| tst.ts:325:7:325:14 | [VarDecl] ErrorMap | semmle.label | [VarDecl] ErrorMap |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | semmle.label | [VariableDeclarator] ErrorMa ... Error> |
+| tst.ts:325:18:325:20 | [VarRef] Map | semmle.label | [VarRef] Map |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | semmle.label | [ExpressionWithTypeArguments] Map |
+| tst.ts:325:22:325:27 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:325:30:325:34 | [LocalTypeAccess] Error | semmle.label | [LocalTypeAccess] Error |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.label | [DeclStmt] const errorMap = ... |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.order | 69 |
+| tst.ts:327:7:327:14 | [VarDecl] errorMap | semmle.label | [VarDecl] errorMap |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | semmle.label | [VariableDeclarator] errorMa ... orMap() |
+| tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | semmle.label | [NewExpr] new ErrorMap() |
+| tst.ts:327:22:327:29 | [VarRef] ErrorMap | semmle.label | [VarRef] ErrorMap |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.order | 70 |
+| tst.ts:331:6:331:16 | [Identifier] FirstString | semmle.label | [Identifier] FirstString |
+| tst.ts:331:18:331:18 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:331:18:331:18 | [TypeParameter] T | semmle.label | [TypeParameter] T |
+| tst.ts:332:3:332:3 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | semmle.label | [ConditionalTypeExpr] T exten ... : never |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | semmle.label | [TupleTypeExpr] [infer ... nown[]] |
+| tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | semmle.label | [InferTypeExpr] infer S ... string |
+| tst.ts:332:20:332:20 | [Identifier] S | semmle.label | [Identifier] S |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | semmle.label | [TypeParameter] S extends string |
+| tst.ts:332:30:332:35 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | semmle.label | [RestTypeExpr] ...unknown[] |
+| tst.ts:332:41:332:47 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown |
+| tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | semmle.label | [ArrayTypeExpr] unknown[] |
+| tst.ts:333:9:333:9 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
+| tst.ts:334:9:334:13 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.order | 71 |
+| tst.ts:336:6:336:6 | [Identifier] F | semmle.label | [Identifier] F |
+| tst.ts:336:10:336:20 | [LocalTypeAccess] FirstString | semmle.label | [LocalTypeAccess] FirstString |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | semmle.label | [GenericTypeExpr] FirstSt ... olean]> |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | semmle.label | [TupleTypeExpr] ['a' \| ... oolean] |
+| tst.ts:336:23:336:25 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tst.ts:336:29:336:31 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tst.ts:336:34:336:39 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
+| tst.ts:336:42:336:48 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.order | 72 |
+| tst.ts:338:7:338:7 | [VarDecl] a | semmle.label | [VarDecl] a |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | semmle.label | [VariableDeclarator] a: F = 'a' |
+| tst.ts:338:10:338:10 | [LocalTypeAccess] F | semmle.label | [LocalTypeAccess] F |
+| tst.ts:338:14:338:16 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... void; } |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.order | 73 |
+| tst.ts:342:11:342:15 | [Identifier] State | semmle.label | [Identifier] State |
+| tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.label | [TypeParameter] in out T |
+| tst.ts:342:24:342:24 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:343:3:343:5 | [Label] get | semmle.label | [Label] get |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | semmle.label | [FieldDeclaration] get: () => T; |
+| tst.ts:343:8:343:14 | [FunctionExpr] () => T | semmle.label | [FunctionExpr] () => T |
+| tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | semmle.label | [FunctionTypeExpr] () => T |
+| tst.ts:343:14:343:14 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:344:3:344:5 | [Label] set | semmle.label | [Label] set |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | semmle.label | [FieldDeclaration] set: (v ... > void; |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | semmle.label | [FunctionExpr] (value: T) => void |
+| tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | semmle.label | [FunctionTypeExpr] (value: T) => void |
+| tst.ts:344:9:344:13 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
+| tst.ts:344:16:344:16 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:344:22:344:25 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.label | [DeclStmt] const state = ... |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.order | 74 |
+| tst.ts:347:7:347:11 | [VarDecl] state | semmle.label | [VarDecl] state |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | semmle.label | [VariableDeclarator] state: ... > { } } |
+| tst.ts:347:14:347:18 | [LocalTypeAccess] State | semmle.label | [LocalTypeAccess] State |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | semmle.label | [GenericTypeExpr] State |
+| tst.ts:347:20:347:25 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | semmle.label | [ObjectExpr] {get: ...} |
+| tst.ts:348:3:348:5 | [Label] get | semmle.label | [Label] get |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | semmle.label | [Property] get: () => 42 |
+| tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | semmle.label | [ArrowFunctionExpr] () => 42 |
+| tst.ts:348:14:348:15 | [Literal] 42 | semmle.label | [Literal] 42 |
+| tst.ts:349:3:349:5 | [Label] set | semmle.label | [Label] set |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | semmle.label | [Property] set: (value) => { } |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | semmle.label | [ArrowFunctionExpr] (value) => { } |
+| tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
+| tst.ts:349:19:349:21 | [BlockStmt] { } | semmle.label | [BlockStmt] { } |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.label | [DeclStmt] const fortyTwo = ... |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.order | 75 |
+| tst.ts:352:7:352:14 | [VarDecl] fortyTwo | semmle.label | [VarDecl] fortyTwo |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | semmle.label | [VariableDeclarator] fortyTw ... e.get() |
+| tst.ts:352:18:352:22 | [VarRef] state | semmle.label | [VarRef] state |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | semmle.label | [DotExpr] state.get |
+| tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | semmle.label | [MethodCallExpr] state.get() |
+| tst.ts:352:24:352:26 | [Label] get | semmle.label | [Label] get |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.label | [ImportDeclaration] import ... S.mjs'; |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.order | 76 |
+| tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | semmle.label | [ImportSpecifier] tstModuleES |
+| tst.ts:356:8:356:18 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
+| tst.ts:356:25:356:43 | [Literal] './tstModuleES.mjs' | semmle.label | [Literal] './tstModuleES.mjs' |
+| tst.ts:358:1:358:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | semmle.label | [MethodCallExpr] console ... leES()) |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.label | [ExprStmt] console ... eES()); |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.order | 77 |
+| tst.ts:358:9:358:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:358:13:358:23 | [VarRef] tstModuleES | semmle.label | [VarRef] tstModuleES |
+| tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | semmle.label | [CallExpr] tstModuleES() |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.label | [ImportDeclaration] import ... S.cjs'; |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.order | 78 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | semmle.label | [ImportSpecifier] tstModuleCJS |
+| tst.ts:360:10:360:21 | [Label] tstModuleCJS | semmle.label | [Label] tstModuleCJS |
+| tst.ts:360:10:360:21 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
+| tst.ts:360:30:360:49 | [Literal] './tstModuleCJS.cjs' | semmle.label | [Literal] './tstModuleCJS.cjs' |
+| tst.ts:362:1:362:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | semmle.label | [MethodCallExpr] console ... eCJS()) |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.label | [ExprStmt] console ... CJS()); |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.order | 79 |
+| tst.ts:362:9:362:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:362:13:362:24 | [VarRef] tstModuleCJS | semmle.label | [VarRef] tstModuleCJS |
+| tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | semmle.label | [CallExpr] tstModuleCJS() |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.label | [ImportDeclaration] import ... ffixA'; |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.order | 80 |
+| tst.ts:368:8:368:13 | [ImportSpecifier] * as A | semmle.label | [ImportSpecifier] * as A |
+| tst.ts:368:13:368:13 | [VarDecl] A | semmle.label | [VarDecl] A |
+| tst.ts:368:20:368:33 | [Literal] './tstSuffixA' | semmle.label | [Literal] './tstSuffixA' |
+| tst.ts:370:1:370:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.order | 81 |
+| tst.ts:370:9:370:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:370:13:370:13 | [VarRef] A | semmle.label | [VarRef] A |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | semmle.label | [DotExpr] A.resolvedFile |
+| tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.label | [MethodCallExpr] A.resolvedFile() |
+| tst.ts:370:15:370:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.label | [ImportDeclaration] import ... ffixB'; |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.order | 82 |
+| tst.ts:372:8:372:13 | [ImportSpecifier] * as B | semmle.label | [ImportSpecifier] * as B |
+| tst.ts:372:13:372:13 | [VarDecl] B | semmle.label | [VarDecl] B |
+| tst.ts:372:20:372:33 | [Literal] './tstSuffixB' | semmle.label | [Literal] './tstSuffixB' |
+| tst.ts:374:1:374:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.order | 83 |
+| tst.ts:374:9:374:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:374:13:374:13 | [VarRef] B | semmle.label | [VarRef] B |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | [DotExpr] B.resolvedFile |
+| tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | [MethodCallExpr] B.resolvedFile() |
+| tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 84 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
+| tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
+| tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tstModuleCJS.cts:1:39:1:41 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | [BlockStmt] { r ... 'b'; } |
+| tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | [ReturnStmt] return ... : 'b'; |
+| tstModuleCJS.cts:2:12:2:15 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | [BinaryExpr] Math.random() > 0.5 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | [ConditionalExpr] Math.ra ... ' : 'b' |
+| tstModuleCJS.cts:2:17:2:22 | [Label] random | semmle.label | [Label] random |
+| tstModuleCJS.cts:2:28:2:30 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 85 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
+| tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
+| tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tstModuleES.mts:1:46:1:48 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | [BlockStmt] { r ... 'b'; } |
+| tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | [ReturnStmt] return ... : 'b'; |
+| tstModuleES.mts:2:12:2:15 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | [BinaryExpr] Math.random() > 0.5 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | [ConditionalExpr] Math.ra ... ' : 'b' |
+| tstModuleES.mts:2:17:2:22 | [Label] random | semmle.label | [Label] random |
+| tstModuleES.mts:2:28:2:30 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 86 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' |
+| tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; |
+| tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 87 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' |
+| tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; |
+| tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 88 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' |
+| tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; |
+| tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; |
-| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 61 |
+| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 89 |
| type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B |
| type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... |
-| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 62 |
+| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 90 |
| type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b |
| type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B |
| type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; |
-| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 63 |
+| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 91 |
| type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray |
| type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T |
| type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T |
@@ -1150,14 +1463,14 @@ nodes
| type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... |
-| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 64 |
+| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 92 |
| type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> |
| type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray |
| type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; |
-| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 65 |
+| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 93 |
| type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json |
| type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] |
| type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -1173,12 +1486,12 @@ nodes
| type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... |
-| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 66 |
+| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 94 |
| type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json |
| type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json |
| type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; |
-| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 67 |
+| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 95 |
| type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode |
| type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] |
| type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -1194,7 +1507,7 @@ nodes
| type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
| type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... |
-| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 68 |
+| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 96 |
| type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode |
| type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] |
| type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
@@ -1219,12 +1532,12 @@ nodes
| type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" |
| type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 69 |
+| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 97 |
| type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} |
-| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 70 |
+| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 98 |
| type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} |
| type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
@@ -1232,36 +1545,36 @@ nodes
| type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
| type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... |
-| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 71 |
+| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 99 |
| type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj |
| type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C |
| type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} |
-| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 72 |
+| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 100 |
| type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} |
| type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... |
-| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 73 |
+| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 101 |
| type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj |
| type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E |
| type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} |
-| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 74 |
+| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 102 |
| type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} |
| type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N |
| type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... |
-| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 75 |
+| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 103 |
| type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj |
| type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N |
| type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 76 |
+| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 104 |
| type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } |
-| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 77 |
+| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 105 |
| type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I |
| type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S |
| type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S |
@@ -1269,14 +1582,14 @@ nodes
| type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; |
| type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... |
-| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 78 |
+| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 106 |
| type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i |
| type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I |
| type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I |
| type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I |
| type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } |
-| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 79 |
+| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 107 |
| type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
| type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} |
@@ -1288,14 +1601,14 @@ nodes
| type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T |
| type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... |
-| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 80 |
+| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 108 |
| type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C |
| type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C |
| type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C |
| type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } |
-| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 81 |
+| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 109 |
| type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color |
| type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red |
| type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red |
@@ -1304,29 +1617,29 @@ nodes
| type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue |
| type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue |
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... |
-| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 82 |
+| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 110 |
| type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color |
| type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color |
| type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color |
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } |
-| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 83 |
+| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 111 |
| type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember |
| type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member |
| type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member |
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... |
-| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 84 |
+| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 112 |
| type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e |
| type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember |
| type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember |
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; |
-| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 85 |
+| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 113 |
| type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias |
| type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T |
| type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
| type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] |
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... |
-| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 86 |
+| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 114 |
| type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray |
| type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> |
| type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias |
@@ -1471,6 +1784,16 @@ edges
| file://:0:0:0:0 | (Arguments) | tst.ts:282:17:287:3 | [ObjectExpr] {kind: ...} | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | tst.ts:285:19:285:35 | [MethodCallExpr] val.toUpperCase() | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | tst.ts:285:19:285:35 | [MethodCallExpr] val.toUpperCase() | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:28:14:28 | [SimpleParameter] y | semmle.label | 1 |
@@ -1529,6 +1852,20 @@ edges
| file://:0:0:0:0 | (Parameters) | tst.ts:291:21:291:24 | [SimpleParameter] kind | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:291:27:291:33 | [SimpleParameter] payload | semmle.label | 1 |
| file://:0:0:0:0 | (Parameters) | tst.ts:291:27:291:33 | [SimpleParameter] payload | semmle.order | 1 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:313:15:313:17 | [SimpleParameter] arg | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:313:15:313:17 | [SimpleParameter] arg | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:314:13:314:13 | [SimpleParameter] n | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:314:13:314:13 | [SimpleParameter] n | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:315:13:315:13 | [SimpleParameter] x | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:315:13:315:13 | [SimpleParameter] x | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:319:12:319:12 | [SimpleParameter] n | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:319:12:319:12 | [SimpleParameter] n | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:320:12:320:12 | [SimpleParameter] x | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:320:12:320:12 | [SimpleParameter] x | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:344:9:344:13 | [SimpleParameter] value | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:344:9:344:13 | [SimpleParameter] value | semmle.order | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.label | 0 |
+| file://:0:0:0:0 | (Parameters) | tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | type_alias.ts:21:19:21:21 | [SimpleParameter] key | semmle.label | 0 |
@@ -1539,6 +1876,14 @@ edges
| file://:0:0:0:0 | (TypeParameters) | tst.ts:272:6:272:11 | [TypeParameter] K in P | semmle.order | 0 |
| file://:0:0:0:0 | (TypeParameters) | tst.ts:278:26:278:48 | [TypeParameter] K exten ... TypeMap | semmle.label | 0 |
| file://:0:0:0:0 | (TypeParameters) | tst.ts:278:26:278:48 | [TypeParameter] K exten ... TypeMap | semmle.order | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:313:12:313:12 | [TypeParameter] T | semmle.label | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:313:12:313:12 | [TypeParameter] T | semmle.order | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:331:18:331:18 | [TypeParameter] T | semmle.label | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:331:18:331:18 | [TypeParameter] T | semmle.order | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:332:20:332:35 | [TypeParameter] S extends string | semmle.label | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:332:20:332:35 | [TypeParameter] S extends string | semmle.order | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.label | 0 |
+| file://:0:0:0:0 | (TypeParameters) | tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.order | 0 |
| file://:0:0:0:0 | (TypeParameters) | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | 0 |
| file://:0:0:0:0 | (TypeParameters) | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.order | 0 |
| file://:0:0:0:0 | (TypeParameters) | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | 0 |
@@ -3351,6 +3696,488 @@ edges
| tst.ts:293:7:293:23 | [MethodCallExpr] payload.toFixed() | tst.ts:293:7:293:21 | [DotExpr] payload.toFixed | semmle.order | 0 |
| tst.ts:293:7:293:24 | [ExprStmt] payload.toFixed(); | tst.ts:293:7:293:23 | [MethodCallExpr] payload.toFixed() | semmle.label | 1 |
| tst.ts:293:7:293:24 | [ExprStmt] payload.toFixed(); | tst.ts:293:7:293:23 | [MethodCallExpr] payload.toFixed() | semmle.order | 1 |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | semmle.label | 1 |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | semmle.order | 1 |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | tst.ts:298:7:298:9 | [VarDecl] key | semmle.label | 1 |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | tst.ts:298:7:298:9 | [VarDecl] key | semmle.order | 1 |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | tst.ts:298:13:298:20 | [CallExpr] Symbol() | semmle.label | 2 |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | tst.ts:298:13:298:20 | [CallExpr] Symbol() | semmle.order | 2 |
+| tst.ts:298:13:298:20 | [CallExpr] Symbol() | tst.ts:298:13:298:18 | [VarRef] Symbol | semmle.label | 0 |
+| tst.ts:298:13:298:20 | [CallExpr] Symbol() | tst.ts:298:13:298:18 | [VarRef] Symbol | semmle.order | 0 |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | semmle.label | 1 |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | semmle.order | 1 |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | tst.ts:300:7:300:20 | [VarDecl] numberOrString | semmle.label | 1 |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | tst.ts:300:7:300:20 | [VarDecl] numberOrString | semmle.order | 1 |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | semmle.label | 2 |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | semmle.order | 2 |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | tst.ts:300:24:300:27 | [VarRef] Math | semmle.label | 1 |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | tst.ts:300:24:300:27 | [VarRef] Math | semmle.order | 1 |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | tst.ts:300:29:300:34 | [Label] random | semmle.label | 2 |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | tst.ts:300:29:300:34 | [Label] random | semmle.order | 2 |
+| tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | tst.ts:300:24:300:34 | [DotExpr] Math.random | semmle.label | 0 |
+| tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | tst.ts:300:24:300:34 | [DotExpr] Math.random | semmle.order | 0 |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | semmle.label | 1 |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | semmle.order | 1 |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | tst.ts:300:40:300:42 | [Literal] 0.5 | semmle.label | 2 |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | tst.ts:300:40:300:42 | [Literal] 0.5 | semmle.order | 2 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | semmle.label | 1 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | semmle.order | 1 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:46:300:47 | [Literal] 42 | semmle.label | 2 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:46:300:47 | [Literal] 42 | semmle.order | 2 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:51:300:57 | [Literal] "hello" | semmle.label | 3 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | tst.ts:300:51:300:57 | [Literal] "hello" | semmle.order | 3 |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | semmle.label | 1 |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | semmle.order | 1 |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | tst.ts:302:5:302:7 | [VarDecl] obj | semmle.label | 1 |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | tst.ts:302:5:302:7 | [VarDecl] obj | semmle.order | 1 |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | semmle.label | 2 |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | semmle.order | 2 |
+| tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | tst.ts:303:3:303:23 | [Property] [key]: ... rString | semmle.label | 1 |
+| tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | tst.ts:303:3:303:23 | [Property] [key]: ... rString | semmle.order | 1 |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | tst.ts:303:4:303:6 | [VarRef] key | semmle.label | 1 |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | tst.ts:303:4:303:6 | [VarRef] key | semmle.order | 1 |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | tst.ts:303:10:303:23 | [VarRef] numberOrString | semmle.label | 2 |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | tst.ts:303:10:303:23 | [VarRef] numberOrString | semmle.order | 2 |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | semmle.label | 1 |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | semmle.order | 1 |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | semmle.label | 2 |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | semmle.order | 2 |
+| tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | tst.ts:306:12:306:19 | [IndexExpr] obj[key] | semmle.label | 1 |
+| tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | tst.ts:306:12:306:19 | [IndexExpr] obj[key] | semmle.order | 1 |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | semmle.label | 1 |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | semmle.order | 1 |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | tst.ts:306:25:306:32 | [Literal] "string" | semmle.label | 2 |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | tst.ts:306:25:306:32 | [Literal] "string" | semmle.order | 2 |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | tst.ts:306:12:306:14 | [VarRef] obj | semmle.label | 1 |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | tst.ts:306:12:306:14 | [VarRef] obj | semmle.order | 1 |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | tst.ts:306:16:306:18 | [VarRef] key | semmle.label | 2 |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | tst.ts:306:16:306:18 | [VarRef] key | semmle.order | 2 |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | tst.ts:307:3:307:21 | [DeclStmt] let str = ... | semmle.label | 1 |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | tst.ts:307:3:307:21 | [DeclStmt] let str = ... | semmle.order | 1 |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | semmle.label | 2 |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | semmle.order | 2 |
+| tst.ts:307:3:307:21 | [DeclStmt] let str = ... | tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | semmle.label | 1 |
+| tst.ts:307:3:307:21 | [DeclStmt] let str = ... | tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | semmle.order | 1 |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | tst.ts:307:7:307:9 | [VarDecl] str | semmle.label | 1 |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | tst.ts:307:7:307:9 | [VarDecl] str | semmle.order | 1 |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | tst.ts:307:13:307:20 | [IndexExpr] obj[key] | semmle.label | 2 |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | tst.ts:307:13:307:20 | [IndexExpr] obj[key] | semmle.order | 2 |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | tst.ts:307:13:307:15 | [VarRef] obj | semmle.label | 1 |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | tst.ts:307:13:307:15 | [VarRef] obj | semmle.order | 1 |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | tst.ts:307:17:307:19 | [VarRef] key | semmle.label | 2 |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | tst.ts:307:17:307:19 | [VarRef] key | semmle.order | 2 |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | tst.ts:308:3:308:5 | [VarRef] str | semmle.label | 1 |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | tst.ts:308:3:308:5 | [VarRef] str | semmle.order | 1 |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | tst.ts:308:7:308:17 | [Label] toUpperCase | semmle.label | 2 |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | tst.ts:308:7:308:17 | [Label] toUpperCase | semmle.order | 2 |
+| tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | semmle.label | 0 |
+| tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | semmle.order | 0 |
+| tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | semmle.label | 1 |
+| tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | semmle.order | 1 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | file://:0:0:0:0 | (TypeParameters) | semmle.label | 2 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | file://:0:0:0:0 | (TypeParameters) | semmle.order | 2 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:313:10:313:10 | [VarDecl] f | semmle.label | 0 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:313:10:313:10 | [VarDecl] f | semmle.order | 0 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:316:4:316:7 | [KeywordTypeExpr] void | semmle.label | 4 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:316:4:316:7 | [KeywordTypeExpr] void | semmle.order | 4 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:316:9:316:10 | [BlockStmt] {} | semmle.label | 5 |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | tst.ts:316:9:316:10 | [BlockStmt] {} | semmle.order | 5 |
+| tst.ts:313:12:313:12 | [TypeParameter] T | tst.ts:313:12:313:12 | [Identifier] T | semmle.label | 1 |
+| tst.ts:313:12:313:12 | [TypeParameter] T | tst.ts:313:12:313:12 | [Identifier] T | semmle.order | 1 |
+| tst.ts:313:15:313:17 | [SimpleParameter] arg | tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | semmle.label | 0 |
+| tst.ts:313:15:313:17 | [SimpleParameter] arg | tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | semmle.order | 0 |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | semmle.label | 1 |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | semmle.order | 1 |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | semmle.label | 2 |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | semmle.order | 2 |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | tst.ts:314:3:314:9 | [Label] produce | semmle.label | 1 |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | tst.ts:314:3:314:9 | [Label] produce | semmle.order | 1 |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | semmle.label | 2 |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | semmle.order | 2 |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | tst.ts:314:27:314:27 | [LocalTypeAccess] T | semmle.label | 4 |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | tst.ts:314:27:314:27 | [LocalTypeAccess] T | semmle.order | 4 |
+| tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | semmle.label | 1 |
+| tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | semmle.order | 1 |
+| tst.ts:314:13:314:13 | [SimpleParameter] n | tst.ts:314:16:314:21 | [KeywordTypeExpr] string | semmle.label | 0 |
+| tst.ts:314:13:314:13 | [SimpleParameter] n | tst.ts:314:16:314:21 | [KeywordTypeExpr] string | semmle.order | 0 |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | tst.ts:315:3:315:9 | [Label] consume | semmle.label | 1 |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | tst.ts:315:3:315:9 | [Label] consume | semmle.order | 1 |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | semmle.label | 2 |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | semmle.order | 2 |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | tst.ts:315:22:315:25 | [KeywordTypeExpr] void | semmle.label | 4 |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | tst.ts:315:22:315:25 | [KeywordTypeExpr] void | semmle.order | 4 |
+| tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | semmle.label | 1 |
+| tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | semmle.order | 1 |
+| tst.ts:315:13:315:13 | [SimpleParameter] x | tst.ts:315:16:315:16 | [LocalTypeAccess] T | semmle.label | 0 |
+| tst.ts:315:13:315:13 | [SimpleParameter] x | tst.ts:315:16:315:16 | [LocalTypeAccess] T | semmle.order | 0 |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | tst.ts:318:1:318:1 | [VarRef] f | semmle.label | 0 |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | tst.ts:318:1:318:1 | [VarRef] f | semmle.order | 0 |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | semmle.label | 1 |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | semmle.order | 1 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | tst.ts:319:3:319:17 | [Property] produce: n => n | semmle.label | 1 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | tst.ts:319:3:319:17 | [Property] produce: n => n | semmle.order | 1 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | tst.ts:320:3:320:31 | [Property] consume ... rCase() | semmle.label | 2 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | tst.ts:320:3:320:31 | [Property] consume ... rCase() | semmle.order | 2 |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | tst.ts:319:3:319:9 | [Label] produce | semmle.label | 1 |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | tst.ts:319:3:319:9 | [Label] produce | semmle.order | 1 |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | semmle.label | 2 |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | semmle.order | 2 |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | tst.ts:319:17:319:17 | [VarRef] n | semmle.label | 5 |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | tst.ts:319:17:319:17 | [VarRef] n | semmle.order | 5 |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | tst.ts:320:3:320:9 | [Label] consume | semmle.label | 1 |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | tst.ts:320:3:320:9 | [Label] consume | semmle.order | 1 |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | semmle.label | 2 |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | semmle.order | 2 |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | semmle.label | 5 |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | semmle.order | 5 |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | tst.ts:320:17:320:17 | [VarRef] x | semmle.label | 1 |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | tst.ts:320:17:320:17 | [VarRef] x | semmle.order | 1 |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | tst.ts:320:19:320:29 | [Label] toLowerCase | semmle.label | 2 |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | tst.ts:320:19:320:29 | [Label] toLowerCase | semmle.order | 2 |
+| tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | semmle.label | 0 |
+| tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | semmle.order | 0 |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | semmle.label | 1 |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | semmle.order | 1 |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | tst.ts:325:7:325:14 | [VarDecl] ErrorMap | semmle.label | 1 |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | tst.ts:325:7:325:14 | [VarDecl] ErrorMap | semmle.order | 1 |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | semmle.label | 2 |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | semmle.order | 2 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:18:325:20 | [VarRef] Map | semmle.label | 1 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:18:325:20 | [VarRef] Map | semmle.order | 1 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:22:325:27 | [KeywordTypeExpr] string | semmle.label | 2 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:22:325:27 | [KeywordTypeExpr] string | semmle.order | 2 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:30:325:34 | [LocalTypeAccess] Error | semmle.label | 3 |
+| tst.ts:325:18:325:35 | [ExpressionWithTypeArguments] Map | tst.ts:325:30:325:34 | [LocalTypeAccess] Error | semmle.order | 3 |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | semmle.label | 1 |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | semmle.order | 1 |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | tst.ts:327:7:327:14 | [VarDecl] errorMap | semmle.label | 1 |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | tst.ts:327:7:327:14 | [VarDecl] errorMap | semmle.order | 1 |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | semmle.label | 2 |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | semmle.order | 2 |
+| tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | tst.ts:327:22:327:29 | [VarRef] ErrorMap | semmle.label | 0 |
+| tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | tst.ts:327:22:327:29 | [VarRef] ErrorMap | semmle.order | 0 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | file://:0:0:0:0 | (TypeParameters) | semmle.label | -100 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | file://:0:0:0:0 | (TypeParameters) | semmle.order | -100 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | tst.ts:331:6:331:16 | [Identifier] FirstString | semmle.label | 1 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | tst.ts:331:6:331:16 | [Identifier] FirstString | semmle.order | 1 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | semmle.label | 3 |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | semmle.order | 3 |
+| tst.ts:331:18:331:18 | [TypeParameter] T | tst.ts:331:18:331:18 | [Identifier] T | semmle.label | 1 |
+| tst.ts:331:18:331:18 | [TypeParameter] T | tst.ts:331:18:331:18 | [Identifier] T | semmle.order | 1 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:332:3:332:3 | [LocalTypeAccess] T | semmle.label | 1 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:332:3:332:3 | [LocalTypeAccess] T | semmle.order | 1 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | semmle.label | 2 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | semmle.order | 2 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:333:9:333:9 | [LocalTypeAccess] S | semmle.label | 3 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:333:9:333:9 | [LocalTypeAccess] S | semmle.order | 3 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:334:9:334:13 | [KeywordTypeExpr] never | semmle.label | 4 |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | tst.ts:334:9:334:13 | [KeywordTypeExpr] never | semmle.order | 4 |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | semmle.label | 1 |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | semmle.order | 1 |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | semmle.label | 2 |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | semmle.order | 2 |
+| tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | file://:0:0:0:0 | (TypeParameters) | semmle.label | -100 |
+| tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | file://:0:0:0:0 | (TypeParameters) | semmle.order | -100 |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | tst.ts:332:20:332:20 | [Identifier] S | semmle.label | 1 |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | tst.ts:332:20:332:20 | [Identifier] S | semmle.order | 1 |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | tst.ts:332:30:332:35 | [KeywordTypeExpr] string | semmle.label | 2 |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | tst.ts:332:30:332:35 | [KeywordTypeExpr] string | semmle.order | 2 |
+| tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | semmle.label | 1 |
+| tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | semmle.order | 1 |
+| tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | tst.ts:332:41:332:47 | [KeywordTypeExpr] unknown | semmle.label | 1 |
+| tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | tst.ts:332:41:332:47 | [KeywordTypeExpr] unknown | semmle.order | 1 |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | tst.ts:336:6:336:6 | [Identifier] F | semmle.label | 1 |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | tst.ts:336:6:336:6 | [Identifier] F | semmle.order | 1 |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | semmle.label | 2 |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | semmle.order | 2 |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | tst.ts:336:10:336:20 | [LocalTypeAccess] FirstString | semmle.label | 1 |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | tst.ts:336:10:336:20 | [LocalTypeAccess] FirstString | semmle.order | 1 |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | semmle.label | 2 |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | semmle.order | 2 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | 1 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | semmle.order | 1 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:34:336:39 | [KeywordTypeExpr] number | semmle.label | 2 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:34:336:39 | [KeywordTypeExpr] number | semmle.order | 2 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:42:336:48 | [KeywordTypeExpr] boolean | semmle.label | 3 |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | tst.ts:336:42:336:48 | [KeywordTypeExpr] boolean | semmle.order | 3 |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | tst.ts:336:23:336:25 | [LiteralTypeExpr] 'a' | semmle.label | 1 |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | tst.ts:336:23:336:25 | [LiteralTypeExpr] 'a' | semmle.order | 1 |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | tst.ts:336:29:336:31 | [LiteralTypeExpr] 'b' | semmle.label | 2 |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | tst.ts:336:29:336:31 | [LiteralTypeExpr] 'b' | semmle.order | 2 |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | semmle.label | 1 |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | semmle.order | 1 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:7:338:7 | [VarDecl] a | semmle.label | 1 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:7:338:7 | [VarDecl] a | semmle.order | 1 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:10:338:10 | [LocalTypeAccess] F | semmle.label | 2 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:10:338:10 | [LocalTypeAccess] F | semmle.order | 2 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:14:338:16 | [Literal] 'a' | semmle.label | 3 |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | tst.ts:338:14:338:16 | [Literal] 'a' | semmle.order | 3 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | file://:0:0:0:0 | (TypeParameters) | semmle.label | -100 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | file://:0:0:0:0 | (TypeParameters) | semmle.order | -100 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:342:11:342:15 | [Identifier] State | semmle.label | 1 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:342:11:342:15 | [Identifier] State | semmle.order | 1 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | semmle.label | 3 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | semmle.order | 3 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | semmle.label | 4 |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | semmle.order | 4 |
+| tst.ts:342:17:342:24 | [TypeParameter] in out T | tst.ts:342:24:342:24 | [Identifier] T | semmle.label | 1 |
+| tst.ts:342:17:342:24 | [TypeParameter] in out T | tst.ts:342:24:342:24 | [Identifier] T | semmle.order | 1 |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | tst.ts:343:3:343:5 | [Label] get | semmle.label | 1 |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | tst.ts:343:3:343:5 | [Label] get | semmle.order | 1 |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | semmle.label | 2 |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | semmle.order | 2 |
+| tst.ts:343:8:343:14 | [FunctionExpr] () => T | tst.ts:343:14:343:14 | [LocalTypeAccess] T | semmle.label | 4 |
+| tst.ts:343:8:343:14 | [FunctionExpr] () => T | tst.ts:343:14:343:14 | [LocalTypeAccess] T | semmle.order | 4 |
+| tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | tst.ts:343:8:343:14 | [FunctionExpr] () => T | semmle.label | 1 |
+| tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | tst.ts:343:8:343:14 | [FunctionExpr] () => T | semmle.order | 1 |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | tst.ts:344:3:344:5 | [Label] set | semmle.label | 1 |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | tst.ts:344:3:344:5 | [Label] set | semmle.order | 1 |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | semmle.label | 2 |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | semmle.order | 2 |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | tst.ts:344:22:344:25 | [KeywordTypeExpr] void | semmle.label | 4 |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | tst.ts:344:22:344:25 | [KeywordTypeExpr] void | semmle.order | 4 |
+| tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | semmle.label | 1 |
+| tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | semmle.order | 1 |
+| tst.ts:344:9:344:13 | [SimpleParameter] value | tst.ts:344:16:344:16 | [LocalTypeAccess] T | semmle.label | 0 |
+| tst.ts:344:9:344:13 | [SimpleParameter] value | tst.ts:344:16:344:16 | [LocalTypeAccess] T | semmle.order | 0 |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | semmle.label | 1 |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | semmle.order | 1 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:7:347:11 | [VarDecl] state | semmle.label | 1 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:7:347:11 | [VarDecl] state | semmle.order | 1 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:14:347:26 | [GenericTypeExpr] State | semmle.label | 2 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:14:347:26 | [GenericTypeExpr] State | semmle.order | 2 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | semmle.label | 3 |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | semmle.order | 3 |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | tst.ts:347:14:347:18 | [LocalTypeAccess] State | semmle.label | 1 |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | tst.ts:347:14:347:18 | [LocalTypeAccess] State | semmle.order | 1 |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | tst.ts:347:20:347:25 | [KeywordTypeExpr] number | semmle.label | 2 |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | tst.ts:347:20:347:25 | [KeywordTypeExpr] number | semmle.order | 2 |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | tst.ts:348:3:348:15 | [Property] get: () => 42 | semmle.label | 1 |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | tst.ts:348:3:348:15 | [Property] get: () => 42 | semmle.order | 1 |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | tst.ts:349:3:349:21 | [Property] set: (value) => { } | semmle.label | 2 |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | tst.ts:349:3:349:21 | [Property] set: (value) => { } | semmle.order | 2 |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | tst.ts:348:3:348:5 | [Label] get | semmle.label | 1 |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | tst.ts:348:3:348:5 | [Label] get | semmle.order | 1 |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | semmle.label | 2 |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | semmle.order | 2 |
+| tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | tst.ts:348:14:348:15 | [Literal] 42 | semmle.label | 5 |
+| tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | tst.ts:348:14:348:15 | [Literal] 42 | semmle.order | 5 |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | tst.ts:349:3:349:5 | [Label] set | semmle.label | 1 |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | tst.ts:349:3:349:5 | [Label] set | semmle.order | 1 |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | semmle.label | 2 |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | semmle.order | 2 |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | tst.ts:349:19:349:21 | [BlockStmt] { } | semmle.label | 5 |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | tst.ts:349:19:349:21 | [BlockStmt] { } | semmle.order | 5 |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | semmle.label | 1 |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | semmle.order | 1 |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | tst.ts:352:7:352:14 | [VarDecl] fortyTwo | semmle.label | 1 |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | tst.ts:352:7:352:14 | [VarDecl] fortyTwo | semmle.order | 1 |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | semmle.label | 2 |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | semmle.order | 2 |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | tst.ts:352:18:352:22 | [VarRef] state | semmle.label | 1 |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | tst.ts:352:18:352:22 | [VarRef] state | semmle.order | 1 |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | tst.ts:352:24:352:26 | [Label] get | semmle.label | 2 |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | tst.ts:352:24:352:26 | [Label] get | semmle.order | 2 |
+| tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | tst.ts:352:18:352:26 | [DotExpr] state.get | semmle.label | 0 |
+| tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | tst.ts:352:18:352:26 | [DotExpr] state.get | semmle.order | 0 |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | semmle.label | 1 |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | semmle.order | 1 |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | tst.ts:356:25:356:43 | [Literal] './tstModuleES.mjs' | semmle.label | 2 |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | tst.ts:356:25:356:43 | [Literal] './tstModuleES.mjs' | semmle.order | 2 |
+| tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | tst.ts:356:8:356:18 | [VarDecl] tstModuleES | semmle.label | 1 |
+| tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | tst.ts:356:8:356:18 | [VarDecl] tstModuleES | semmle.order | 1 |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | tst.ts:358:1:358:7 | [VarRef] console | semmle.label | 1 |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | tst.ts:358:1:358:7 | [VarRef] console | semmle.order | 1 |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | tst.ts:358:9:358:11 | [Label] log | semmle.label | 2 |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | tst.ts:358:9:358:11 | [Label] log | semmle.order | 2 |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | tst.ts:358:1:358:11 | [DotExpr] console.log | semmle.label | 0 |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | tst.ts:358:1:358:11 | [DotExpr] console.log | semmle.order | 0 |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | semmle.label | 1 |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | semmle.order | 1 |
+| tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | tst.ts:358:13:358:23 | [VarRef] tstModuleES | semmle.label | 0 |
+| tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | tst.ts:358:13:358:23 | [VarRef] tstModuleES | semmle.order | 0 |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | semmle.label | 1 |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | semmle.order | 1 |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | tst.ts:360:30:360:49 | [Literal] './tstModuleCJS.cjs' | semmle.label | 2 |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | tst.ts:360:30:360:49 | [Literal] './tstModuleCJS.cjs' | semmle.order | 2 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | tst.ts:360:10:360:21 | [Label] tstModuleCJS | semmle.label | 1 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | tst.ts:360:10:360:21 | [Label] tstModuleCJS | semmle.order | 1 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | tst.ts:360:10:360:21 | [VarDecl] tstModuleCJS | semmle.label | 2 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | tst.ts:360:10:360:21 | [VarDecl] tstModuleCJS | semmle.order | 2 |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | tst.ts:362:1:362:7 | [VarRef] console | semmle.label | 1 |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | tst.ts:362:1:362:7 | [VarRef] console | semmle.order | 1 |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | tst.ts:362:9:362:11 | [Label] log | semmle.label | 2 |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | tst.ts:362:9:362:11 | [Label] log | semmle.order | 2 |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | tst.ts:362:1:362:11 | [DotExpr] console.log | semmle.label | 0 |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | tst.ts:362:1:362:11 | [DotExpr] console.log | semmle.order | 0 |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | semmle.label | 1 |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | semmle.order | 1 |
+| tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | tst.ts:362:13:362:24 | [VarRef] tstModuleCJS | semmle.label | 0 |
+| tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | tst.ts:362:13:362:24 | [VarRef] tstModuleCJS | semmle.order | 0 |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | tst.ts:368:8:368:13 | [ImportSpecifier] * as A | semmle.label | 1 |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | tst.ts:368:8:368:13 | [ImportSpecifier] * as A | semmle.order | 1 |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | tst.ts:368:20:368:33 | [Literal] './tstSuffixA' | semmle.label | 2 |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | tst.ts:368:20:368:33 | [Literal] './tstSuffixA' | semmle.order | 2 |
+| tst.ts:368:8:368:13 | [ImportSpecifier] * as A | tst.ts:368:13:368:13 | [VarDecl] A | semmle.label | 1 |
+| tst.ts:368:8:368:13 | [ImportSpecifier] * as A | tst.ts:368:13:368:13 | [VarDecl] A | semmle.order | 1 |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | tst.ts:370:1:370:7 | [VarRef] console | semmle.label | 1 |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | tst.ts:370:1:370:7 | [VarRef] console | semmle.order | 1 |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | tst.ts:370:9:370:11 | [Label] log | semmle.label | 2 |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | tst.ts:370:9:370:11 | [Label] log | semmle.order | 2 |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | tst.ts:370:1:370:11 | [DotExpr] console.log | semmle.label | 0 |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | tst.ts:370:1:370:11 | [DotExpr] console.log | semmle.order | 0 |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | semmle.label | 1 |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | semmle.order | 1 |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | tst.ts:370:13:370:13 | [VarRef] A | semmle.label | 1 |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | tst.ts:370:13:370:13 | [VarRef] A | semmle.order | 1 |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | tst.ts:370:15:370:26 | [Label] resolvedFile | semmle.label | 2 |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | tst.ts:370:15:370:26 | [Label] resolvedFile | semmle.order | 2 |
+| tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | semmle.label | 0 |
+| tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | semmle.order | 0 |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | tst.ts:372:8:372:13 | [ImportSpecifier] * as B | semmle.label | 1 |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | tst.ts:372:8:372:13 | [ImportSpecifier] * as B | semmle.order | 1 |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | tst.ts:372:20:372:33 | [Literal] './tstSuffixB' | semmle.label | 2 |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | tst.ts:372:20:372:33 | [Literal] './tstSuffixB' | semmle.order | 2 |
+| tst.ts:372:8:372:13 | [ImportSpecifier] * as B | tst.ts:372:13:372:13 | [VarDecl] B | semmle.label | 1 |
+| tst.ts:372:8:372:13 | [ImportSpecifier] * as B | tst.ts:372:13:372:13 | [VarDecl] B | semmle.order | 1 |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | tst.ts:374:1:374:7 | [VarRef] console | semmle.label | 1 |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | tst.ts:374:1:374:7 | [VarRef] console | semmle.order | 1 |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | tst.ts:374:9:374:11 | [Label] log | semmle.label | 2 |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | tst.ts:374:9:374:11 | [Label] log | semmle.order | 2 |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | tst.ts:374:1:374:11 | [DotExpr] console.log | semmle.label | 0 |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | tst.ts:374:1:374:11 | [DotExpr] console.log | semmle.order | 0 |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | semmle.label | 1 |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | semmle.order | 1 |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | tst.ts:374:13:374:13 | [VarRef] B | semmle.label | 1 |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | tst.ts:374:13:374:13 | [VarRef] B | semmle.order | 1 |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.label | 2 |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.order | 2 |
+| tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | 0 |
+| tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.order | 0 |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | 0 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.order | 0 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | 4 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | semmle.order | 4 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | 5 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | semmle.order | 5 |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | 1 |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.order | 1 |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | tstModuleCJS.cts:1:39:1:41 | [LiteralTypeExpr] 'b' | semmle.label | 2 |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | tstModuleCJS.cts:1:39:1:41 | [LiteralTypeExpr] 'b' | semmle.order | 2 |
+| tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | 1 |
+| tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.order | 1 |
+| tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | 1 |
+| tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.order | 1 |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | tstModuleCJS.cts:2:12:2:15 | [VarRef] Math | semmle.label | 1 |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | tstModuleCJS.cts:2:12:2:15 | [VarRef] Math | semmle.order | 1 |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | tstModuleCJS.cts:2:17:2:22 | [Label] random | semmle.label | 2 |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | tstModuleCJS.cts:2:17:2:22 | [Label] random | semmle.order | 2 |
+| tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | semmle.label | 0 |
+| tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | semmle.order | 0 |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | 1 |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.order | 1 |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleCJS.cts:2:28:2:30 | [Literal] 0.5 | semmle.label | 2 |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleCJS.cts:2:28:2:30 | [Literal] 0.5 | semmle.order | 2 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | 1 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.order | 1 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | 2 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.order | 2 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | 3 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.order | 3 |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | 0 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.order | 0 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | 4 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | semmle.order | 4 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | 5 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | semmle.order | 5 |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | 1 |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.order | 1 |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | tstModuleES.mts:1:46:1:48 | [LiteralTypeExpr] 'b' | semmle.label | 2 |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | tstModuleES.mts:1:46:1:48 | [LiteralTypeExpr] 'b' | semmle.order | 2 |
+| tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | 1 |
+| tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.order | 1 |
+| tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | 1 |
+| tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.order | 1 |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | tstModuleES.mts:2:12:2:15 | [VarRef] Math | semmle.label | 1 |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | tstModuleES.mts:2:12:2:15 | [VarRef] Math | semmle.order | 1 |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | tstModuleES.mts:2:17:2:22 | [Label] random | semmle.label | 2 |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | tstModuleES.mts:2:17:2:22 | [Label] random | semmle.order | 2 |
+| tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | semmle.label | 0 |
+| tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | semmle.order | 0 |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | 1 |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.order | 1 |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleES.mts:2:28:2:30 | [Literal] 0.5 | semmle.label | 2 |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | tstModuleES.mts:2:28:2:30 | [Literal] 0.5 | semmle.order | 2 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | 1 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.order | 1 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | 2 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.order | 2 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | 3 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.order | 3 |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | 1 |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.order | 1 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | 0 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.order | 0 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | 4 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.order | 4 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | 5 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.order | 5 |
+| tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | 1 |
+| tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.order | 1 |
+| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | 1 |
+| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.order | 1 |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | 1 |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.order | 1 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | 0 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.order | 0 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | 4 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.order | 4 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | 5 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | semmle.order | 5 |
+| tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | 1 |
+| tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.order | 1 |
+| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | 1 |
+| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.order | 1 |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | 1 |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.order | 1 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | 0 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.order | 0 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | 4 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.order | 4 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | 5 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.order | 5 |
+| tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | 1 |
+| tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.order | 1 |
+| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | 1 |
+| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.order | 1 |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | 1 |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.order | 1 |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | 2 |
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
index 4e85a6fe95c..ce517db8d6d 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
@@ -386,6 +386,148 @@ getExprType
| tst.ts:293:7:293:21 | payload.toFixed | (fractionDigits?: number) => string |
| tst.ts:293:7:293:23 | payload.toFixed() | string |
| tst.ts:293:15:293:21 | toFixed | (fractionDigits?: number) => string |
+| tst.ts:298:7:298:9 | key | typeof key |
+| tst.ts:298:13:298:18 | Symbol | SymbolConstructor |
+| tst.ts:298:13:298:20 | Symbol() | typeof key |
+| tst.ts:300:7:300:20 | numberOrString | "hello" \| 42 |
+| tst.ts:300:24:300:27 | Math | Math |
+| tst.ts:300:24:300:34 | Math.random | () => number |
+| tst.ts:300:24:300:36 | Math.random() | number |
+| tst.ts:300:24:300:42 | Math.random() < 0.5 | boolean |
+| tst.ts:300:24:300:57 | Math.ra ... "hello" | "hello" \| 42 |
+| tst.ts:300:29:300:34 | random | () => number |
+| tst.ts:300:40:300:42 | 0.5 | 0.5 |
+| tst.ts:300:46:300:47 | 42 | 42 |
+| tst.ts:300:51:300:57 | "hello" | "hello" |
+| tst.ts:302:5:302:7 | obj | { [key]: string \| number; } |
+| tst.ts:302:11:304:1 | {\\n [ke ... ring,\\n} | { [key]: string \| number; } |
+| tst.ts:303:4:303:6 | key | typeof key |
+| tst.ts:303:10:303:23 | numberOrString | "hello" \| 42 |
+| tst.ts:306:5:306:19 | typeof obj[key] | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
+| tst.ts:306:5:306:32 | typeof ... string" | boolean |
+| tst.ts:306:12:306:14 | obj | { [key]: string \| number; } |
+| tst.ts:306:12:306:19 | obj[key] | string \| number |
+| tst.ts:306:16:306:18 | key | typeof key |
+| tst.ts:306:25:306:32 | "string" | "string" |
+| tst.ts:307:7:307:9 | str | string |
+| tst.ts:307:13:307:15 | obj | { [key]: string \| number; } |
+| tst.ts:307:13:307:20 | obj[key] | string |
+| tst.ts:307:17:307:19 | key | typeof key |
+| tst.ts:308:3:308:5 | str | string |
+| tst.ts:308:3:308:17 | str.toUpperCase | () => string |
+| tst.ts:308:3:308:19 | str.toUpperCase() | string |
+| tst.ts:308:7:308:17 | toUpperCase | () => string |
+| tst.ts:313:10:313:10 | f | (arg: { produce: (n: string) => T; consume: ... |
+| tst.ts:313:15:313:17 | arg | { produce: (n: string) => T; consume: (x: T) =>... |
+| tst.ts:314:3:314:9 | produce | (n: string) => T |
+| tst.ts:314:12:314:27 | (n: string) => T | (n: string) => T |
+| tst.ts:314:13:314:13 | n | string |
+| tst.ts:315:3:315:9 | consume | (x: T) => void |
+| tst.ts:315:12:315:25 | (x: T) => void | (x: T) => void |
+| tst.ts:315:13:315:13 | x | T |
+| tst.ts:318:1:318:1 | f | (arg: { produce: (n: string) => T; consume: ... |
+| tst.ts:318:1:321:2 | f({\\n p ... se()\\n}) | void |
+| tst.ts:318:3:321:1 | {\\n pro ... ase()\\n} | { produce: (n: string) => string; consume: (x: ... |
+| tst.ts:319:3:319:9 | produce | (n: string) => string |
+| tst.ts:319:12:319:12 | n | string |
+| tst.ts:319:12:319:17 | n => n | (n: string) => string |
+| tst.ts:319:17:319:17 | n | string |
+| tst.ts:320:3:320:9 | consume | (x: string) => string |
+| tst.ts:320:12:320:12 | x | string |
+| tst.ts:320:12:320:31 | x => x.toLowerCase() | (x: string) => string |
+| tst.ts:320:17:320:17 | x | string |
+| tst.ts:320:17:320:29 | x.toLowerCase | () => string |
+| tst.ts:320:17:320:31 | x.toLowerCase() | string |
+| tst.ts:320:19:320:29 | toLowerCase | () => string |
+| tst.ts:325:7:325:14 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
+| tst.ts:325:18:325:20 | Map | MapConstructor |
+| tst.ts:325:18:325:35 | Map | any |
+| tst.ts:327:7:327:14 | errorMap | Map |
+| tst.ts:327:18:327:31 | new ErrorMap() | Map |
+| tst.ts:327:22:327:29 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
+| tst.ts:338:7:338:7 | a | "a" \| "b" |
+| tst.ts:338:14:338:16 | 'a' | "a" |
+| tst.ts:343:3:343:5 | get | () => T |
+| tst.ts:343:8:343:14 | () => T | () => T |
+| tst.ts:344:3:344:5 | set | (value: T) => void |
+| tst.ts:344:8:344:25 | (value: T) => void | (value: T) => void |
+| tst.ts:344:9:344:13 | value | T |
+| tst.ts:347:7:347:11 | state | State |
+| tst.ts:347:30:350:1 | {\\n get ... > { }\\n} | State |
+| tst.ts:348:3:348:5 | get | () => number |
+| tst.ts:348:8:348:15 | () => 42 | () => number |
+| tst.ts:348:14:348:15 | 42 | 42 |
+| tst.ts:349:3:349:5 | set | (value: number) => void |
+| tst.ts:349:8:349:21 | (value) => { } | (value: number) => void |
+| tst.ts:349:9:349:13 | value | number |
+| tst.ts:352:7:352:14 | fortyTwo | number |
+| tst.ts:352:18:352:22 | state | State |
+| tst.ts:352:18:352:26 | state.get | () => number |
+| tst.ts:352:18:352:28 | state.get() | number |
+| tst.ts:352:24:352:26 | get | () => number |
+| tst.ts:356:8:356:18 | tstModuleES | () => "a" \| "b" |
+| tst.ts:356:25:356:43 | './tstModuleES.mjs' | any |
+| tst.ts:358:1:358:7 | console | Console |
+| tst.ts:358:1:358:11 | console.log | (...data: any[]) => void |
+| tst.ts:358:1:358:26 | console ... leES()) | void |
+| tst.ts:358:9:358:11 | log | (...data: any[]) => void |
+| tst.ts:358:13:358:23 | tstModuleES | () => "a" \| "b" |
+| tst.ts:358:13:358:25 | tstModuleES() | "a" \| "b" |
+| tst.ts:360:10:360:21 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:360:10:360:21 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:360:30:360:49 | './tstModuleCJS.cjs' | any |
+| tst.ts:362:1:362:7 | console | Console |
+| tst.ts:362:1:362:11 | console.log | (...data: any[]) => void |
+| tst.ts:362:1:362:27 | console ... eCJS()) | void |
+| tst.ts:362:9:362:11 | log | (...data: any[]) => void |
+| tst.ts:362:13:362:24 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:362:13:362:26 | tstModuleCJS() | "a" \| "b" |
+| tst.ts:368:13:368:13 | A | typeof library-tests/TypeScript/Types/tstSuffixA.ts |
+| tst.ts:368:20:368:33 | './tstSuffixA' | any |
+| tst.ts:370:1:370:7 | console | Console |
+| tst.ts:370:1:370:11 | console.log | (...data: any[]) => void |
+| tst.ts:370:1:370:29 | console ... File()) | void |
+| tst.ts:370:9:370:11 | log | (...data: any[]) => void |
+| tst.ts:370:13:370:13 | A | typeof library-tests/TypeScript/Types/tstSuffixA.ts |
+| tst.ts:370:13:370:26 | A.resolvedFile | () => "tstSuffixA.ts" |
+| tst.ts:370:13:370:28 | A.resolvedFile() | "tstSuffixA.ts" |
+| tst.ts:370:15:370:26 | resolvedFile | () => "tstSuffixA.ts" |
+| tst.ts:372:13:372:13 | B | typeof library-tests/TypeScript/Types/tstSuffixB.ios.ts |
+| tst.ts:372:20:372:33 | './tstSuffixB' | any |
+| tst.ts:374:1:374:7 | console | Console |
+| tst.ts:374:1:374:11 | console.log | (...data: any[]) => void |
+| tst.ts:374:1:374:29 | console ... File()) | void |
+| tst.ts:374:9:374:11 | log | (...data: any[]) => void |
+| tst.ts:374:13:374:13 | B | typeof library-tests/TypeScript/Types/tstSuffixB.ios.ts |
+| tst.ts:374:13:374:26 | B.resolvedFile | () => "tstSuffixB.ios.ts" |
+| tst.ts:374:13:374:28 | B.resolvedFile() | "tstSuffixB.ios.ts" |
+| tst.ts:374:15:374:26 | resolvedFile | () => "tstSuffixB.ios.ts" |
+| tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" |
+| tstModuleCJS.cts:2:12:2:15 | Math | Math |
+| tstModuleCJS.cts:2:12:2:22 | Math.random | () => number |
+| tstModuleCJS.cts:2:12:2:24 | Math.random() | number |
+| tstModuleCJS.cts:2:12:2:30 | Math.random() > 0.5 | boolean |
+| tstModuleCJS.cts:2:12:2:42 | Math.ra ... ' : 'b' | "a" \| "b" |
+| tstModuleCJS.cts:2:17:2:22 | random | () => number |
+| tstModuleCJS.cts:2:28:2:30 | 0.5 | 0.5 |
+| tstModuleCJS.cts:2:34:2:36 | 'a' | "a" |
+| tstModuleCJS.cts:2:40:2:42 | 'b' | "b" |
+| tstModuleES.mts:1:25:1:35 | tstModuleES | () => "a" \| "b" |
+| tstModuleES.mts:2:12:2:15 | Math | Math |
+| tstModuleES.mts:2:12:2:22 | Math.random | () => number |
+| tstModuleES.mts:2:12:2:24 | Math.random() | number |
+| tstModuleES.mts:2:12:2:30 | Math.random() > 0.5 | boolean |
+| tstModuleES.mts:2:12:2:42 | Math.ra ... ' : 'b' | "a" \| "b" |
+| tstModuleES.mts:2:17:2:22 | random | () => number |
+| tstModuleES.mts:2:28:2:30 | 0.5 | 0.5 |
+| tstModuleES.mts:2:34:2:36 | 'a' | "a" |
+| tstModuleES.mts:2:40:2:42 | 'b' | "b" |
+| tstSuffixA.ts:1:17:1:28 | resolvedFile | () => "tstSuffixA.ts" |
+| tstSuffixA.ts:2:12:2:26 | 'tstSuffixA.ts' | "tstSuffixA.ts" |
+| tstSuffixB.ios.ts:1:17:1:28 | resolvedFile | () => "tstSuffixB.ios.ts" |
+| tstSuffixB.ios.ts:2:12:2:30 | 'tstSuffixB.ios.ts' | "tstSuffixB.ios.ts" |
+| tstSuffixB.ts:1:17:1:28 | resolvedFile | () => "tstSuffixB.ts" |
+| tstSuffixB.ts:2:12:2:26 | 'tstSuffixB.ts' | "tstSuffixB.ts" |
| type_alias.ts:3:5:3:5 | b | boolean |
| type_alias.ts:7:5:7:5 | c | ValueOrArray |
| type_alias.ts:14:9:14:32 | [proper ... ]: Json | any |
@@ -461,6 +603,9 @@ getTypeDefinitionType
| tst.ts:265:3:269:3 | interfa ... an;\\n } | TypeMap |
| tst.ts:271:3:276:7 | type Un ... }[P]; | UnionRecord |
| tst.ts:289:3:289:63 | type Fu ... > void; | Func |
+| tst.ts:331:1:334:14 | type Fi ... never; | FirstString |
+| tst.ts:336:1:336:51 | type F ... lean]>; | "a" \| "b" |
+| tst.ts:342:1:345:1 | interfa ... void;\\n} | State |
| type_alias.ts:1:1:1:17 | type B = boolean; | boolean |
| type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray |
| type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json |
@@ -703,6 +848,48 @@ getTypeExprType
| tst.ts:289:47:289:52 | string | string |
| tst.ts:289:59:289:62 | void | void |
| tst.ts:291:13:291:16 | Func | Func |
+| tst.ts:313:12:313:12 | T | T |
+| tst.ts:313:20:315:27 | {\\n pro ... void } | { produce: (n: string) => T; consume: (x: T) =>... |
+| tst.ts:314:12:314:27 | (n: string) => T | (n: string) => T |
+| tst.ts:314:16:314:21 | string | string |
+| tst.ts:314:27:314:27 | T | T |
+| tst.ts:315:12:315:25 | (x: T) => void | (x: T) => void |
+| tst.ts:315:16:315:16 | T | T |
+| tst.ts:315:22:315:25 | void | void |
+| tst.ts:316:4:316:7 | void | void |
+| tst.ts:325:22:325:27 | string | string |
+| tst.ts:325:30:325:34 | Error | Error |
+| tst.ts:331:6:331:16 | FirstString | FirstString |
+| tst.ts:331:18:331:18 | T | T |
+| tst.ts:336:6:336:6 | F | "a" \| "b" |
+| tst.ts:336:10:336:20 | FirstString | FirstString |
+| tst.ts:336:10:336:50 | FirstSt ... olean]> | "a" \| "b" |
+| tst.ts:336:22:336:49 | ['a' \| ... oolean] | ["a" \| "b", number, boolean] |
+| tst.ts:336:23:336:25 | 'a' | "a" |
+| tst.ts:336:23:336:31 | 'a' \| 'b' | "a" \| "b" |
+| tst.ts:336:29:336:31 | 'b' | "b" |
+| tst.ts:336:34:336:39 | number | number |
+| tst.ts:336:42:336:48 | boolean | boolean |
+| tst.ts:338:10:338:10 | F | "a" \| "b" |
+| tst.ts:342:11:342:15 | State | State |
+| tst.ts:342:24:342:24 | T | T |
+| tst.ts:343:8:343:14 | () => T | () => T |
+| tst.ts:343:14:343:14 | T | T |
+| tst.ts:344:8:344:25 | (value: T) => void | (value: T) => void |
+| tst.ts:344:16:344:16 | T | T |
+| tst.ts:344:22:344:25 | void | void |
+| tst.ts:347:14:347:18 | State | State |
+| tst.ts:347:14:347:26 | State | State |
+| tst.ts:347:20:347:25 | number | number |
+| tstModuleCJS.cts:1:33:1:35 | 'a' | "a" |
+| tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" |
+| tstModuleCJS.cts:1:39:1:41 | 'b' | "b" |
+| tstModuleES.mts:1:40:1:42 | 'a' | "a" |
+| tstModuleES.mts:1:40:1:48 | 'a' \| 'b' | "a" \| "b" |
+| tstModuleES.mts:1:46:1:48 | 'b' | "b" |
+| tstSuffixA.ts:1:33:1:47 | 'tstSuffixA.ts' | "tstSuffixA.ts" |
+| tstSuffixB.ios.ts:1:33:1:51 | 'tstSuffixB.ios.ts' | "tstSuffixB.ios.ts" |
+| tstSuffixB.ts:1:33:1:47 | 'tstSuffixB.ts' | "tstSuffixB.ts" |
| type_alias.ts:1:6:1:6 | B | boolean |
| type_alias.ts:1:10:1:16 | boolean | boolean |
| type_alias.ts:3:8:3:8 | B | boolean |
@@ -783,6 +970,7 @@ referenceDefinition
| E | type_definition_objects.ts:6:8:6:16 | enum E {} |
| EnumWithOneMember | type_definitions.ts:18:26:18:31 | member |
| Error | tst.ts:210:10:213:3 | interfa ... ng;\\n } |
+| FirstString | tst.ts:331:1:334:14 | type Fi ... never; |
| Foo | tst.ts:116:3:129:3 | class F ... }\\n } |
| Foo | tst.ts:165:5:167:5 | interfa ... ;\\n } |
| Foo | tst.ts:179:3:192:3 | class F ... \\n } |
@@ -796,6 +984,8 @@ referenceDefinition
| NonAbstractDummy | tst.ts:54:1:56:1 | interfa ... mber;\\n} |
| Person | tst.ts:222:3:234:3 | class P ... }\\n } |
| Shape | tst.ts:140:3:142:47 | type Sh ... mber }; |
+| State | tst.ts:342:1:345:1 | interfa ... void;\\n} |
+| State | tst.ts:342:1:345:1 | interfa ... void;\\n} |
| Sub | tst.ts:97:3:101:3 | class S ... }\\n } |
| Success | tst.ts:205:10:208:3 | interfa ... ng;\\n } |
| Super | tst.ts:91:3:95:3 | class S ... }\\n } |
@@ -852,16 +1042,20 @@ abstractSignature
unionIndex
| 1 | 0 | 1 \| 2 |
| 2 | 1 | 1 \| 2 |
+| 42 | 1 | "hello" \| 42 |
| "NumberContents" | 0 | "NumberContents" \| "StringContents" |
| "StringContents" | 1 | "NumberContents" \| "StringContents" |
| "a" | 0 | "a" \| "b" |
| "a" | 1 | number \| "a" |
+| "a" | 3 | number \| boolean \| "a" \| "b" |
| "b" | 1 | "a" \| "b" |
+| "b" | 4 | number \| boolean \| "a" \| "b" |
| "bigint" | 2 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "boolean" | 2 | keyof TypeMap |
| "boolean" | 3 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "circle" | 0 | "circle" \| "square" |
| "function" | 7 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
+| "hello" | 0 | "hello" \| 42 |
| "number" | 1 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "number" | 1 | keyof TypeMap |
| "object" | 6 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
@@ -871,6 +1065,7 @@ unionIndex
| "symbol" | 4 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "undefined" | 5 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| Error | 1 | Success \| Error |
+| Error | 1 | string \| Error |
| Json[] | 5 | string \| number \| boolean \| { [property: string... |
| Promise | 2 | boolean \| Promise |
| PromiseLike | 1 | TResult1 \| PromiseLike |
@@ -890,16 +1085,19 @@ unionIndex
| false | 0 | boolean |
| false | 0 | boolean \| Promise |
| false | 1 | number \| boolean |
+| false | 1 | number \| boolean \| "a" \| "b" |
| false | 2 | string \| number \| boolean |
| false | 2 | string \| number \| boolean \| { [property: string... |
| number | 0 | number \| "a" |
| number | 0 | number \| ValueOrArray[] |
| number | 0 | number \| boolean |
+| number | 0 | number \| boolean \| "a" \| "b" |
| number | 1 | string \| number |
| number | 1 | string \| number \| boolean |
| number | 1 | string \| number \| boolean \| { [property: string... |
| number | 1 | string \| number \| true |
| string | 0 | VirtualNode \| { [key: string]: any; } |
+| string | 0 | string \| Error |
| string | 0 | string \| [string, { [key: string]: any; }, ...V... |
| string | 0 | string \| number |
| string | 0 | string \| number \| boolean |
@@ -911,6 +1109,7 @@ unionIndex
| true | 1 | boolean |
| true | 1 | boolean \| Promise |
| true | 2 | number \| boolean |
+| true | 2 | number \| boolean \| "a" \| "b" |
| true | 2 | string \| number \| true |
| true | 3 | string \| number \| boolean |
| true | 3 | string \| number \| boolean \| { [property: string... |
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json b/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
index f6aa3a1e752..2235cec7f7d 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
@@ -3,6 +3,7 @@
"module": "esnext",
"target": "esnext",
"lib": ["dom", "esnext"],
- "resolveJsonModule": true
+ "resolveJsonModule": true,
+ "moduleSuffixes": [".ios", ""]
}
}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
index 9fdb0d950c4..ed8787112d3 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
@@ -293,4 +293,83 @@ module TS46 {
payload.toFixed(); // <- number
}
};
-}
\ No newline at end of file
+}
+
+const key = Symbol();
+
+const numberOrString = Math.random() < 0.5 ? 42 : "hello";
+
+let obj = {
+ [key]: numberOrString,
+};
+
+if (typeof obj[key] === "string") {
+ let str = obj[key]; // <- string
+ str.toUpperCase();
+}
+
+//////////
+
+function f(arg: {
+ produce: (n: string) => T,
+ consume: (x: T) => void }
+): void {};
+
+f({
+ produce: n => n, // <- (n: string) => string
+ consume: x => x.toLowerCase()
+});
+
+///////////
+
+const ErrorMap = Map;
+
+const errorMap = new ErrorMap(); // <- Map
+
+////////////
+
+type FirstString =
+ T extends [infer S extends string, ...unknown[]]
+ ? S
+ : never;
+
+type F = FirstString<['a' | 'b', number, boolean]>;
+
+const a: F = 'a'; // <- 'a' | 'b'
+
+////////////
+
+interface State {
+ get: () => T;
+ set: (value: T) => void;
+}
+
+const state: State = {
+ get: () => 42,
+ set: (value) => { }
+}
+
+const fortyTwo = state.get(); // <- number
+
+/////////////////
+
+import tstModuleES from './tstModuleES.mjs';
+
+console.log(tstModuleES());
+
+import { tstModuleCJS } from './tstModuleCJS.cjs';
+
+console.log(tstModuleCJS());
+
+/////////////////
+
+// test file resolution order (see tsconfig: moduleSuffixes setting)
+
+import * as A from './tstSuffixA';
+
+console.log(A.resolvedFile()); // <- 'tstSuffixA.ts'
+
+import * as B from './tstSuffixB';
+
+console.log(B.resolvedFile()); // <- 'tstSuffixB.ios.ts'
+
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts
new file mode 100644
index 00000000000..c764c1e1243
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts
@@ -0,0 +1,3 @@
+export function tstModuleCJS(): 'a' | 'b' {
+ return Math.random() > 0.5 ? 'a' : 'b';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts
new file mode 100644
index 00000000000..cf735d1bb49
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts
@@ -0,0 +1,3 @@
+export default function tstModuleES(): 'a' | 'b' {
+ return Math.random() > 0.5 ? 'a' : 'b';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts
new file mode 100644
index 00000000000..ffe0b811492
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixA.ts' {
+ return 'tstSuffixA.ts';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts
new file mode 100644
index 00000000000..04463fc7699
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixB.ios.ts' {
+ return 'tstSuffixB.ios.ts';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts
new file mode 100644
index 00000000000..cdb26f8f614
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixB.ts' {
+ return 'tstSuffixB.ts';
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
index 76a21469f6b..9578d5139b5 100644
--- a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
+++ b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
@@ -1,3 +1,5 @@
import javascript
-query DataFlow::Node dbUse() { result = API::moduleImport("@example/db").getInstance().getAUse() }
+query DataFlow::Node dbUse() {
+ result = API::moduleImport("@example/db").getInstance().getAValueReachableFromSource()
+}
diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql
index bdc08e3706f..ff385f3afff 100644
--- a/javascript/ql/test/library-tests/frameworks/data/test.ql
+++ b/javascript/ql/test/library-tests/frameworks/data/test.ql
@@ -62,13 +62,13 @@ class BasicTaintTracking extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CallNode).getCalleeName() = "source"
or
- source = ModelOutput::getASourceNode("test-source").getAnImmediateUse()
+ source = ModelOutput::getASourceNode("test-source").asSource()
}
override predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- sink = ModelOutput::getASinkNode("test-sink").getARhs()
+ sink = ModelOutput::getASinkNode("test-sink").asSink()
}
}
@@ -77,7 +77,7 @@ query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
}
query predicate isSink(DataFlow::Node node, string kind) {
- node = ModelOutput::getASinkNode(kind).getARhs()
+ node = ModelOutput::getASinkNode(kind).asSink()
}
class SyntaxErrorTest extends ModelInput::SinkModelCsv {
diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
index 26cd1a110bb..847f30bd944 100644
--- a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
+++ b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
@@ -81,3 +81,11 @@
(function(){
({ unusedProp: 42 }, 42);
});
+
+(function(){
+ var foo = {
+ unused: 42
+ };
+ foo.unused = 42;
+ Object.hasOwn(foo, blab);
+});
diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected b/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected
index 9db0d903c2d..73be1f62b89 100644
--- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected
+++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/UnusedVariable.expected
@@ -5,6 +5,7 @@
| eval.js:19:9:19:24 | not_used_by_eval | Unused variable not_used_by_eval. |
| externs.js:6:5:6:13 | iAmUnused | Unused variable iAmUnused. |
| importWithoutPragma.jsx:1:1:1:27 | import ... react'; | Unused import h. |
+| interTypes.ts:1:1:1:37 | import ... where"; | Unused import Bar. |
| multi-imports.js:1:1:1:29 | import ... om 'x'; | Unused imports a, b, d. |
| multi-imports.js:2:1:2:42 | import ... om 'x'; | Unused imports alphabetically, ordered. |
| namespaceImportAsType.ts:3:1:3:23 | import ... om "z"; | Unused import Z. |
diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/interTypes.ts b/javascript/ql/test/query-tests/Declarations/UnusedVariable/interTypes.ts
new file mode 100644
index 00000000000..bdcd767fae8
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/interTypes.ts
@@ -0,0 +1,6 @@
+import { Foo, Bar } from "somewhere"; // OK
+
+type FooBar =
+ T extends [infer S extends Foo, ...unknown[]]
+ ? S
+ : never;
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
index a4654b29c27..5fa8a043558 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
@@ -50,6 +50,13 @@ nodes
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
+| express.js:150:7:150:34 | target |
+| express.js:150:16:150:34 | req.param("target") |
+| express.js:150:16:150:34 | req.param("target") |
+| express.js:155:18:155:23 | target |
+| express.js:155:18:155:23 | target |
+| express.js:160:18:160:23 | target |
+| express.js:160:18:160:23 | target |
| koa.js:6:6:6:27 | url |
| koa.js:6:12:6:27 | ctx.query.target |
| koa.js:6:12:6:27 | ctx.query.target |
@@ -140,6 +147,12 @@ edges
| express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo |
+| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
+| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
+| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
+| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
+| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
+| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:8:18:8:20 | url |
@@ -199,6 +212,8 @@ edges
| express.js:136:16:136:36 | 'u' + r ... ms.user | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | Untrusted URL redirection due to $@. | express.js:136:22:136:36 | req.params.user | user-provided value |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | Untrusted URL redirection due to $@. | express.js:143:16:143:28 | req.query.foo | user-provided value |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | Untrusted URL redirection due to $@. | express.js:146:16:146:24 | query.foo | user-provided value |
+| express.js:155:18:155:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:155:18:155:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
+| express.js:160:18:160:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:160:18:160:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
| koa.js:7:15:7:17 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:7:15:7:17 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:8:15:8:26 | `${url}${x}` | koa.js:6:12:6:27 | ctx.query.target | koa.js:8:15:8:26 | `${url}${x}` | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:14:16:14:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:14:16:14:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
index b319315b985..667d6f89f05 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
@@ -144,4 +144,18 @@ app.get("foo", (req, res) => {
});
app.get("bar", ({query}, res) => {
res.redirect(query.foo); // NOT OK
-})
\ No newline at end of file
+})
+
+app.get('/some/path', function(req, res) {
+ let target = req.param("target");
+
+ if (SAFE_TARGETS.hasOwnProperty(target))
+ res.redirect(target); // OK: request parameter is checked against whitelist
+ else
+ res.redirect(target); // NOT OK
+
+ if (Object.hasOwn(SAFE_TARGETS, target))
+ res.redirect(target); // OK: request parameter is checked against whitelist
+ else
+ res.redirect(target); // NOT OK
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/ResourceExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/ResourceExhaustion.expected
index ffbdfd3d5e8..19adec40d24 100644
--- a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/ResourceExhaustion.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/ResourceExhaustion.expected
@@ -17,12 +17,6 @@ nodes
| resource-exhaustion.js:6:7:6:21 | n |
| resource-exhaustion.js:6:11:6:21 | parseInt(s) |
| resource-exhaustion.js:6:20:6:20 | s |
-| resource-exhaustion.js:11:21:11:21 | s |
-| resource-exhaustion.js:11:21:11:21 | s |
-| resource-exhaustion.js:12:21:12:21 | n |
-| resource-exhaustion.js:12:21:12:21 | n |
-| resource-exhaustion.js:13:21:13:21 | n |
-| resource-exhaustion.js:13:21:13:21 | n |
| resource-exhaustion.js:14:16:14:16 | n |
| resource-exhaustion.js:14:16:14:16 | n |
| resource-exhaustion.js:15:22:15:22 | n |
@@ -71,8 +65,6 @@ edges
| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) |
| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) |
| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:6:20:6:20 | s |
-| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:11:21:11:21 | s |
-| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:11:21:11:21 | s |
| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s |
| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s |
| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s |
@@ -84,10 +76,6 @@ edges
| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | resource-exhaustion.js:5:7:5:42 | s |
| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) |
| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) |
-| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n |
-| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n |
-| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n |
-| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n |
| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n |
| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n |
| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n |
@@ -124,9 +112,6 @@ edges
| resource-exhaustion.js:6:20:6:20 | s | resource-exhaustion.js:6:11:6:21 | parseInt(s) |
#select
| documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here |
-| resource-exhaustion.js:11:21:11:21 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:11:21:11:21 | s | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
-| resource-exhaustion.js:12:21:12:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:12:21:12:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
-| resource-exhaustion.js:13:21:13:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:13:21:13:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
| resource-exhaustion.js:14:16:14:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:14:16:14:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
| resource-exhaustion.js:15:22:15:22 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:15:22:15:22 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
| resource-exhaustion.js:16:26:16:26 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:16:26:16:26 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/resource-exhaustion.js b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/resource-exhaustion.js
index e4b8f2ff9e3..ddda361db3a 100644
--- a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/resource-exhaustion.js
+++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion/resource-exhaustion.js
@@ -8,9 +8,9 @@ var server = http.createServer(function(req, res) {
Buffer.from(s); // OK
Buffer.from(n); // OK
Buffer.from(x, n); // OK
- Buffer.from(x, y, s); // NOT OK
- Buffer.from(x, y, n); // NOT OK
- Buffer.from(x, y, n); // NOT OK
+ Buffer.from(x, y, s); // OK - does not allocate memory
+ Buffer.from(x, y, n); // OK - does not allocate memory
+ Buffer.from(x, y, n); // OK - does not allocate memory
Buffer.alloc(n); // NOT OK
Buffer.allocUnsafe(n); // NOT OK
Buffer.allocUnsafeSlow(n); // NOT OK
diff --git a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
index 5c560d8c4ca..997d8968fcc 100644
--- a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
@@ -32,6 +32,18 @@ nodes
| tst.js:81:9:81:9 | p |
| tst.js:82:9:82:9 | p |
| tst.js:82:9:82:9 | p |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
edges
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
@@ -63,6 +75,10 @@ edges
| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p |
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
+| tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo |
+| tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo |
#select
| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |
| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |
@@ -75,3 +91,7 @@ edges
| tst.js:46:5:46:7 | foo | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:46:5:46:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:45:15:45:35 | ctx.req ... ery.foo | this HTTP request parameter |
| tst.js:81:9:81:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:81:9:81:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter |
| tst.js:82:9:82:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:82:9:82:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter |
+| tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:90:5:90:12 | data.foo | this HTTP request parameter |
+| tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:92:9:92:16 | data.foo | this HTTP request parameter |
+| tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:95:9:95:16 | data.foo | this HTTP request parameter |
+| tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:98:9:98:16 | data.foo | this HTTP request parameter |
diff --git a/javascript/ql/test/query-tests/Security/CWE-843/tst.js b/javascript/ql/test/query-tests/Security/CWE-843/tst.js
index 82650bcf054..d49f7ce53d2 100644
--- a/javascript/ql/test/query-tests/Security/CWE-843/tst.js
+++ b/javascript/ql/test/query-tests/Security/CWE-843/tst.js
@@ -1,7 +1,7 @@
var express = require('express');
var Koa = require('koa');
-express().get('/some/path', function(req, res) {
+express().get('/some/path', function (req, res) {
var foo = req.query.foo;
foo.indexOf(); // NOT OK
@@ -41,38 +41,38 @@ express().get('/some/path', function(req, res) {
foo.length; // NOT OK
});
-new Koa().use(function handler(ctx){
+new Koa().use(function handler(ctx) {
var foo = ctx.request.query.foo;
foo.indexOf(); // NOT OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
var foo = req.params.foo;
foo.indexOf(); // OK
});
-express().get('/some/path/:foo', function(req, res) {
- if (req.query.path.length) {} // OK
+express().get('/some/path/:foo', function (req, res) {
+ if (req.query.path.length) { } // OK
req.query.path.length == 0; // OK
!req.query.path.length; // OK
req.query.path.length > 0; // OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
let p = req.query.path;
if (typeof p !== 'string') {
- return;
+ return;
}
while (p.length) { // OK
- p = p.substr(1);
+ p = p.substr(1);
}
p.length < 1; // OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
let someObject = {};
safeGet(someObject, req.query.path).bar = 'baz'; // prototype pollution here - but flagged in `safeGet`
});
@@ -84,3 +84,26 @@ function safeGet(obj, p) {
}
return obj[p];
}
+
+express().get('/foo', function (req, res) {
+ let data = req.query;
+ data.foo.indexOf(); // NOT OK
+ if (typeof data.foo !== 'undefined') {
+ data.foo.indexOf(); // NOT OK
+ }
+ if (typeof data.foo !== 'string') {
+ data.foo.indexOf(); // OK
+ }
+ if (typeof data.foo !== 'undefined') {
+ data.foo.indexOf(); // NOT OK
+ }
+});
+
+express().get('/foo', function (req, res) {
+ let data = req.query;
+ if (Array.isArray(data)) {
+ data.indexOf(); // OK
+ } else {
+ data.indexOf(); // OK
+ }
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
index 23b21f12460..f16f3e4ef55 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
@@ -1478,6 +1478,56 @@ nodes
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
+| tests.js:552:35:552:37 | src |
+| tests.js:552:35:552:37 | src |
+| tests.js:553:14:553:16 | key |
+| tests.js:553:14:553:16 | key |
+| tests.js:553:14:553:16 | key |
+| tests.js:557:43:557:45 | src |
+| tests.js:557:43:557:45 | src |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:24:559:26 | src |
+| tests.js:559:24:559:26 | src |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key |
+| tests.js:559:28:559:30 | key |
+| tests.js:564:35:564:37 | src |
+| tests.js:564:35:564:37 | src |
+| tests.js:565:14:565:16 | key |
+| tests.js:565:14:565:16 | key |
+| tests.js:565:14:565:16 | key |
+| tests.js:569:43:569:45 | src |
+| tests.js:569:43:569:45 | src |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:24:571:26 | src |
+| tests.js:571:24:571:26 | src |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key |
+| tests.js:571:28:571:30 | key |
edges
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
@@ -3347,6 +3397,70 @@ edges
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
+| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
+| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
+| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
+| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
+| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
+| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
+| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
#select
| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst |
| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target |
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
index d54081d6e7d..a1fc92a5776 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
@@ -548,3 +548,27 @@ function mergeUsingCallback3(dst, src) {
}
});
}
+
+function copyHasOwnProperty2(dst, src) {
+ for (let key in src) {
+ // Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
+ // since '__proto__' and 'constructor' are not own properties of the destination object.
+ if (Object.hasOwn(dst, key)) {
+ copyHasOwnProperty2(dst[key], src[key]);
+ } else {
+ dst[key] = src[key]; // OK
+ }
+ }
+}
+
+function copyHasOwnProperty3(dst, src) {
+ for (let key in src) {
+ // Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
+ // since '__proto__' and 'constructor' are not own properties of the destination object.
+ if (_.has(dst, key)) {
+ copyHasOwnProperty3(dst[key], src[key]);
+ } else {
+ dst[key] = src[key]; // OK
+ }
+ }
+}
diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll
index 973e1ea85fa..fcb89e5f866 100644
--- a/python/ql/lib/semmle/python/ApiGraphs.qll
+++ b/python/ql/lib/semmle/python/ApiGraphs.qll
@@ -136,6 +136,9 @@ module API {
result = this.getASuccessor(Label::keywordParameter(name))
}
+ /** Gets the node representing the self parameter */
+ Node getSelfParameter() { result = this.getASuccessor(Label::selfParameter()) }
+
/**
* Gets the number of parameters of the function represented by this node.
*/
@@ -321,6 +324,12 @@ module API {
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = this.getParameter(_) }
+ /** Gets the object that this method-call is being called on, if this is a method-call */
+ Node getSelfParameter() {
+ result.getARhs() = this.(DataFlow::MethodCallNode).getObject() and
+ result = callee.getSelfParameter()
+ }
+
/** Gets the API node for the keyword parameter `name` of this invocation. */
Node getKeywordParameter(string name) {
result = callee.getKeywordParameter(name) and
@@ -345,6 +354,14 @@ module API {
result = callee.getReturn() and
result.getAnImmediateUse() = this
}
+
+ /**
+ * Gets the number of positional arguments of this call.
+ *
+ * Note: This is used for `WithArity[]` in modeling-as-data, where we thought
+ * including keyword arguments didn't make much sense.
+ */
+ int getNumArgument() { result = count(this.getArg(_)) }
}
/**
@@ -589,15 +606,24 @@ module API {
exists(DataFlow::Node def, PY::CallableExpr fn |
rhs(base, def) and fn = trackDefNode(def).asExpr()
|
- exists(int i |
- lbl = Label::parameter(i) and
+ exists(int i, int offset |
+ if exists(PY::Parameter p | p = fn.getInnerScope().getAnArg() and p.isSelf())
+ then offset = 1
+ else offset = 0
+ |
+ lbl = Label::parameter(i - offset) and
ref.asExpr() = fn.getInnerScope().getArg(i)
)
or
- exists(string name |
+ exists(string name, PY::Parameter param |
lbl = Label::keywordParameter(name) and
- ref.asExpr() = fn.getInnerScope().getArgByName(name)
+ param = fn.getInnerScope().getArgByName(name) and
+ not param.isSelf() and
+ ref.asExpr() = param
)
+ or
+ lbl = Label::selfParameter() and
+ ref.asExpr() = any(PY::Parameter p | p = fn.getInnerScope().getAnArg() and p.isSelf())
)
or
// Built-ins, treated as members of the module `builtins`
@@ -664,6 +690,9 @@ module API {
exists(string name | lbl = Label::keywordParameter(name) |
arg = pred.getACall().getArgByName(name)
)
+ or
+ lbl = Label::selfParameter() and
+ arg = pred.getACall().(DataFlow::MethodCallNode).getObject()
)
}
@@ -780,6 +809,7 @@ module API {
or
exists(any(PY::Function f).getArgByName(name))
} or
+ MkLabelSelfParameter() or
MkLabelReturn() or
MkLabelSubclass() or
MkLabelAwait()
@@ -837,6 +867,11 @@ module API {
string getName() { result = name }
}
+ /** A label for the self parameter. */
+ class LabelSelfParameter extends ApiLabel, MkLabelSelfParameter {
+ override string toString() { result = "getSelfParameter()" }
+ }
+
/** A label that gets the return value of a function. */
class LabelReturn extends ApiLabel, MkLabelReturn {
override string toString() { result = "getReturn()" }
@@ -876,6 +911,9 @@ module API {
/** Gets the `parameter` edge label for the keyword parameter `name`. */
LabelKeywordParameter keywordParameter(string name) { result.getName() = name }
+ /** Gets the edge label for the self parameter. */
+ LabelSelfParameter selfParameter() { any() }
+
/** Gets the `return` edge label. */
LabelReturn return() { any() }
diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll
index 4812628d262..daa67ee4231 100644
--- a/python/ql/lib/semmle/python/Frameworks.qll
+++ b/python/ql/lib/semmle/python/Frameworks.qll
@@ -12,6 +12,7 @@ private import semmle.python.frameworks.Asyncpg
private import semmle.python.frameworks.ClickhouseDriver
private import semmle.python.frameworks.Cryptodome
private import semmle.python.frameworks.Cryptography
+private import semmle.python.frameworks.data.ModelsAsData
private import semmle.python.frameworks.Dill
private import semmle.python.frameworks.Django
private import semmle.python.frameworks.Fabric
diff --git a/python/ql/lib/semmle/python/frameworks/Asyncpg.qll b/python/ql/lib/semmle/python/frameworks/Asyncpg.qll
index 5f867fe28ff..81da12a015c 100644
--- a/python/ql/lib/semmle/python/frameworks/Asyncpg.qll
+++ b/python/ql/lib/semmle/python/frameworks/Asyncpg.qll
@@ -7,91 +7,42 @@ private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
+private import semmle.python.frameworks.data.ModelsAsData
/** Provides models for the `asyncpg` PyPI package. */
private module Asyncpg {
- private import semmle.python.internal.Awaited
-
- /** Gets a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited. */
- API::Node connectionPool() {
- result = API::moduleImport("asyncpg").getMember("create_pool").getReturn().getAwaited()
- }
-
- /**
- * Gets a `Connection` that is created when
- * - the result of `asyncpg.connect()` is awaited.
- * - the result of calling `acquire` on a `ConnectionPool` is awaited.
- */
- API::Node connection() {
- result = API::moduleImport("asyncpg").getMember("connect").getReturn().getAwaited()
- or
- result = connectionPool().getMember("acquire").getReturn().getAwaited()
- }
-
- /** `Connection`s and `ConnectionPool`s provide some methods that execute SQL. */
- class SqlExecutionOnConnection extends SqlExecution::Range, DataFlow::MethodCallNode {
- string methodName;
-
- SqlExecutionOnConnection() {
- this = [connectionPool(), connection()].getMember(methodName).getACall() and
- methodName in ["copy_from_query", "execute", "fetch", "fetchrow", "fetchval", "executemany"]
- }
-
- override DataFlow::Node getSql() {
- methodName in ["copy_from_query", "execute", "fetch", "fetchrow", "fetchval"] and
- result in [this.getArg(0), this.getArgByName("query")]
- or
- methodName = "executemany" and
- result in [this.getArg(0), this.getArgByName("command")]
+ class AsyncpgModel extends ModelInput::TypeModelCsv {
+ override predicate row(string row) {
+ // package1;type1;package2;type2;path
+ row =
+ [
+ // a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited.
+ "asyncpg;ConnectionPool;asyncpg;;Member[create_pool].ReturnValue.Awaited",
+ // a `Connection` that is created when
+ // * - the result of `asyncpg.connect()` is awaited.
+ // * - the result of calling `acquire` on a `ConnectionPool` is awaited.
+ "asyncpg;Connection;asyncpg;;Member[connect].ReturnValue.Awaited",
+ "asyncpg;Connection;asyncpg;ConnectionPool;Member[acquire].ReturnValue.Awaited",
+ // Creating an internal `~Connection` type that contains both `Connection` and `ConnectionPool`.
+ "asyncpg;~Connection;asyncpg;Connection;", "asyncpg;~Connection;asyncpg;ConnectionPool;"
+ ]
}
}
- /** A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system. */
- class FileAccessOnConnection extends FileSystemAccess::Range, DataFlow::MethodCallNode {
- string methodName;
-
- FileAccessOnConnection() {
- this = [connectionPool(), connection()].getMember(methodName).getACall() and
- methodName in ["copy_from_query", "copy_from_table", "copy_to_table"]
- }
-
- // The path argument is keyword only.
- override DataFlow::Node getAPathArgument() {
- methodName in ["copy_from_query", "copy_from_table"] and
- result = this.getArgByName("output")
- or
- methodName = "copy_to_table" and
- result = this.getArgByName("source")
- }
- }
-
- /**
- * Provides models of the `PreparedStatement` class in `asyncpg`.
- * `PreparedStatement`s are created when the result of calling `prepare(query)` on a connection is awaited.
- * The result of calling `prepare(query)` is a `PreparedStatementFactory` and the argument, `query` needs to
- * be tracked to the place where a `PreparedStatement` is created and then further to any executing methods.
- * Hence the two type trackers.
- */
- module PreparedStatement {
- class PreparedStatementConstruction extends SqlConstruction::Range, API::CallNode {
- PreparedStatementConstruction() { this = connection().getMember("prepare").getACall() }
-
- override DataFlow::Node getSql() { result = this.getParameter(0, "query").getARhs() }
- }
-
- class PreparedStatementExecution extends SqlExecution::Range, API::CallNode {
- PreparedStatementConstruction prepareCall;
-
- PreparedStatementExecution() {
- this =
- prepareCall
- .getReturn()
- .getAwaited()
- .getMember(["executemany", "fetch", "fetchrow", "fetchval"])
- .getACall()
- }
-
- override DataFlow::Node getSql() { result = prepareCall.getSql() }
+ class AsyncpgSink extends ModelInput::SinkModelCsv {
+ // package;type;path;kind
+ override predicate row(string row) {
+ row =
+ [
+ // `Connection`s and `ConnectionPool`s provide some methods that execute SQL.
+ "asyncpg;~Connection;Member[copy_from_query,execute,fetch,fetchrow,fetchval].Argument[0,query:];sql-injection",
+ "asyncpg;~Connection;Member[executemany].Argument[0,command:];sql-injection",
+ // A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system.
+ "asyncpg;~Connection;Member[copy_from_query,copy_from_table].Argument[output:];path-injection",
+ "asyncpg;~Connection;Member[copy_to_table].Argument[source:];path-injection",
+ // the `PreparedStatement` class in `asyncpg`.
+ "asyncpg;Connection;Member[prepare].Argument[0,query:];sql-injection",
+ ]
}
}
@@ -106,7 +57,9 @@ private module Asyncpg {
*/
module Cursor {
class CursorConstruction extends SqlConstruction::Range, API::CallNode {
- CursorConstruction() { this = connection().getMember("cursor").getACall() }
+ CursorConstruction() {
+ this = ModelOutput::getATypeNode("asyncpg", "Connection").getMember("cursor").getACall()
+ }
override DataFlow::Node getSql() { result = this.getParameter(0, "query").getARhs() }
}
@@ -121,8 +74,11 @@ private module Asyncpg {
this = c.getReturn().getAwaited().getAnImmediateUse()
)
or
- exists(PreparedStatement::PreparedStatementConstruction prepareCall |
- sql = prepareCall.getSql() and
+ exists(API::CallNode prepareCall |
+ prepareCall =
+ ModelOutput::getATypeNode("asyncpg", "Connection").getMember("prepare").getACall()
+ |
+ sql = prepareCall.getParameter(0, "query").getARhs() and
this =
prepareCall
.getReturn()
diff --git a/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll
new file mode 100644
index 00000000000..2af91a69432
--- /dev/null
+++ b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll
@@ -0,0 +1,47 @@
+/**
+ * Provides classes for contributing a model, or using the interpreted results
+ * of a model represented as data.
+ *
+ * - Use the `ModelInput` module to contribute new models.
+ * - Use the `ModelOutput` module to access the model results in terms of API nodes.
+ *
+ * The package name refers to the top-level module the import comes from, and not a PyPI package.
+ * So for `from foo.bar import baz`, the package will be `foo`.
+ */
+
+private import python
+private import internal.ApiGraphModels as Shared
+private import internal.ApiGraphModelsSpecific as Specific
+import Shared::ModelInput as ModelInput
+import Shared::ModelOutput as ModelOutput
+private import semmle.python.dataflow.new.RemoteFlowSources
+private import semmle.python.dataflow.new.DataFlow
+private import semmle.python.ApiGraphs
+private import semmle.python.dataflow.new.TaintTracking
+
+/**
+ * A remote flow source originating from a CSV source row.
+ */
+private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
+ RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").getAnImmediateUse() }
+
+ override string getSourceType() { result = "Remote flow (from model)" }
+}
+
+/**
+ * Like `ModelOutput::summaryStep` but with API nodes mapped to data-flow nodes.
+ */
+private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
+ exists(API::Node predNode, API::Node succNode |
+ Specific::summaryStep(predNode, succNode, kind) and
+ pred = predNode.getARhs() and
+ succ = succNode.getAnImmediateUse()
+ )
+}
+
+/** Taint steps induced by summary models of kind `taint`. */
+private class TaintStepFromSummary extends TaintTracking::AdditionalTaintStep {
+ override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
+ summaryStepNodes(pred, succ, "taint")
+ }
+}
diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll b/python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll
new file mode 100644
index 00000000000..076e12f2671
--- /dev/null
+++ b/python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll
@@ -0,0 +1,182 @@
+/**
+ * Module for parsing access paths from CSV models, both the identifying access path used
+ * by dynamic languages, and the input/output specifications for summary steps.
+ *
+ * This file is used by the shared data flow library and by the JavaScript libraries
+ * (which does not use the shared data flow libraries).
+ */
+
+/**
+ * Convenience-predicate for extracting two capture groups at once.
+ */
+bindingset[input, regexp]
+private predicate regexpCaptureTwo(string input, string regexp, string capture1, string capture2) {
+ capture1 = input.regexpCapture(regexp, 1) and
+ capture2 = input.regexpCapture(regexp, 2)
+}
+
+/** Companion module to the `AccessPath` class. */
+module AccessPath {
+ /** A string that should be parsed as an access path. */
+ abstract class Range extends string {
+ bindingset[this]
+ Range() { any() }
+ }
+
+ /**
+ * Parses an integer constant `n` or interval `n1..n2` (inclusive) and gets the value
+ * of the constant or any value contained in the interval.
+ */
+ bindingset[arg]
+ int parseInt(string arg) {
+ result = arg.toInt()
+ or
+ // Match "n1..n2"
+ exists(string lo, string hi |
+ regexpCaptureTwo(arg, "(-?\\d+)\\.\\.(-?\\d+)", lo, hi) and
+ result = [lo.toInt() .. hi.toInt()]
+ )
+ }
+
+ /**
+ * Parses a lower-bounded interval `n..` and gets the lower bound.
+ */
+ bindingset[arg]
+ int parseLowerBound(string arg) { result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt() }
+
+ /**
+ * Parses an integer constant or interval (bounded or unbounded) that explicitly
+ * references the arity, such as `N-1` or `N-3..N-1`.
+ *
+ * Note that expressions of form `N-x` will never resolve to a negative index,
+ * even if `N` is zero (it will have no result in that case).
+ */
+ bindingset[arg, arity]
+ private int parseIntWithExplicitArity(string arg, int arity) {
+ result >= 0 and // do not allow N-1 to resolve to a negative index
+ exists(string lo |
+ // N-x
+ lo = arg.regexpCapture("N-(\\d+)", 1) and
+ result = arity - lo.toInt()
+ or
+ // N-x..
+ lo = arg.regexpCapture("N-(\\d+)\\.\\.", 1) and
+ result = [arity - lo.toInt(), arity - 1]
+ )
+ or
+ exists(string lo, string hi |
+ // x..N-y
+ regexpCaptureTwo(arg, "(-?\\d+)\\.\\.N-(\\d+)", lo, hi) and
+ result = [lo.toInt() .. arity - hi.toInt()]
+ or
+ // N-x..N-y
+ regexpCaptureTwo(arg, "N-(\\d+)\\.\\.N-(\\d+)", lo, hi) and
+ result = [arity - lo.toInt() .. arity - hi.toInt()] and
+ result >= 0
+ or
+ // N-x..y
+ regexpCaptureTwo(arg, "N-(\\d+)\\.\\.(\\d+)", lo, hi) and
+ result = [arity - lo.toInt() .. hi.toInt()] and
+ result >= 0
+ )
+ }
+
+ /**
+ * Parses an integer constant or interval (bounded or unbounded) and gets any
+ * of the integers contained within (of which there may be infinitely many).
+ *
+ * Has no result for arguments involving an explicit arity, such as `N-1`.
+ */
+ bindingset[arg, result]
+ int parseIntUnbounded(string arg) {
+ result = parseInt(arg)
+ or
+ result >= parseLowerBound(arg)
+ }
+
+ /**
+ * Parses an integer constant or interval (bounded or unbounded) that
+ * may reference the arity of a call, such as `N-1` or `N-3..N-1`.
+ *
+ * Note that expressions of form `N-x` will never resolve to a negative index,
+ * even if `N` is zero (it will have no result in that case).
+ */
+ bindingset[arg, arity]
+ int parseIntWithArity(string arg, int arity) {
+ result = parseInt(arg)
+ or
+ result in [parseLowerBound(arg) .. arity - 1]
+ or
+ result = parseIntWithExplicitArity(arg, arity)
+ }
+}
+
+/** Gets the `n`th token on the access path as a string. */
+private string getRawToken(AccessPath path, int n) {
+ // Avoid splitting by '.' since tokens may contain dots, e.g. `Field[foo.Bar.x]`.
+ // Instead use regexpFind to match valid tokens, and supplement with a final length
+ // check (in `AccessPath.hasSyntaxError`) to ensure all characters were included in a token.
+ result = path.regexpFind("\\w+(?:\\[[^\\]]*\\])?(?=\\.|$)", n, _)
+}
+
+/**
+ * A string that occurs as an access path (either identifying or input/output spec)
+ * which might be relevant for this database.
+ */
+class AccessPath extends string instanceof AccessPath::Range {
+ /** Holds if this string is not a syntactically valid access path. */
+ predicate hasSyntaxError() {
+ // If the lengths match, all characters must haven been included in a token
+ // or seen by the `.` lookahead pattern.
+ this != "" and
+ not this.length() = sum(int n | | getRawToken(this, n).length() + 1) - 1
+ }
+
+ /** Gets the `n`th token on the access path (if there are no syntax errors). */
+ AccessPathToken getToken(int n) {
+ result = getRawToken(this, n) and
+ not this.hasSyntaxError()
+ }
+
+ /** Gets the number of tokens on the path (if there are no syntax errors). */
+ int getNumToken() {
+ result = count(int n | exists(getRawToken(this, n))) and
+ not this.hasSyntaxError()
+ }
+}
+
+/**
+ * An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
+ */
+class AccessPathToken extends string {
+ AccessPathToken() { this = getRawToken(_, _) }
+
+ private string getPart(int part) {
+ result = this.regexpCapture("([^\\[]+)(?:\\[([^\\]]*)\\])?", part)
+ }
+
+ /** Gets the name of the token, such as `Member` from `Member[x]` */
+ string getName() { result = this.getPart(1) }
+
+ /**
+ * Gets the argument list, such as `1,2` from `Member[1,2]`,
+ * or has no result if there are no arguments.
+ */
+ string getArgumentList() { result = this.getPart(2) }
+
+ /** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
+ string getArgument(int n) { result = this.getArgumentList().splitAt(",", n).trim() }
+
+ /** Gets the `n`th argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
+ pragma[nomagic]
+ string getArgument(string name, int n) { name = this.getName() and result = this.getArgument(n) }
+
+ /** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
+ string getAnArgument() { result = this.getArgument(_) }
+
+ /** Gets an argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
+ string getAnArgument(string name) { result = this.getArgument(name, _) }
+
+ /** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
+ int getNumArgument() { result = count(int n | exists(this.getArgument(n))) }
+}
diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll
new file mode 100644
index 00000000000..69563a3eab4
--- /dev/null
+++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll
@@ -0,0 +1,522 @@
+/**
+ * INTERNAL use only. This is an experimental API subject to change without notice.
+ *
+ * Provides classes and predicates for dealing with flow models specified in CSV format.
+ *
+ * The CSV specification has the following columns:
+ * - Sources:
+ * `package; type; path; kind`
+ * - Sinks:
+ * `package; type; path; kind`
+ * - Summaries:
+ * `package; type; path; input; output; kind`
+ * - Types:
+ * `package1; type1; package2; type2; path`
+ *
+ * The interpretation of a row is similar to API-graphs with a left-to-right
+ * reading.
+ * 1. The `package` column selects a package name, as it would be referenced in the source code,
+ * such as an NPM package, PIP package, or Ruby gem. (See `ModelsAsData.qll` for language-specific details).
+ * It may also be a synthetic package used for a type definition (see type definitions below).
+ * 2. The `type` column selects all instances of a named type originating from that package,
+ * or the empty string if referring to the package itself.
+ * It can also be a synthetic type name defined by a type definition (see type definitions below).
+ * 3. The `path` column is a `.`-separated list of "access path tokens" to resolve, starting at the node selected by `package` and `type`.
+ *
+ * Every language supports the following tokens:
+ * - Argument[n]: the n-th argument to a call. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
+ * Additionally, `N-1` refers to the last argument, `N-2` refers to the second-last, and so on.
+ * - Parameter[n]: the n-th parameter of a callback. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
+ * - ReturnValue: the value returned by a function call
+ * - WithArity[n]: match a call with the given arity. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
+ *
+ * The following tokens are common and should be implemented for languages where it makes sense:
+ * - Member[x]: a member named `x`; exactly what a "member" is depends on the language. May be a comma-separated list of names.
+ * - Instance: an instance of a class
+ * - Subclass: a subclass of a class
+ * - ArrayElement: an element of array
+ * - Element: an element of a collection-like object
+ * - MapKey: a key in map-like object
+ * - MapValue: a value in a map-like object
+ * - Awaited: the value from a resolved promise/future-like object
+ *
+ * For the time being, please consult `ApiGraphModelsSpecific.qll` to see which language-specific tokens are currently supported.
+ *
+ * 4. The `input` and `output` columns specify how data enters and leaves the element selected by the
+ * first `(package, type, path)` tuple. Both strings are `.`-separated access paths
+ * of the same syntax as the `path` column.
+ * 5. The `kind` column is a tag that can be referenced from QL to determine to
+ * which classes the interpreted elements should be added. For example, for
+ * sources `"remote"` indicates a default remote flow source, and for summaries
+ * `"taint"` indicates a default additional taint step and `"value"` indicates a
+ * globally applicable value-preserving step.
+ *
+ * ### Types
+ *
+ * A type row of form `package1; type1; package2; type2; path` indicates that `package2; type2; path`
+ * should be seen as an instance of the type `package1; type1`.
+ *
+ * A `(package,type)` pair may refer to a static type or a synthetic type name used internally in the model.
+ * Synthetic type names can be used to reuse intermediate sub-paths, when there are multiple ways to access the same
+ * element.
+ * See `ModelsAsData.qll` for the language-specific interpretation of packages and static type names.
+ *
+ * By convention, if one wants to avoid clashes with static types from the package, the type name
+ * should be prefixed with a tilde character (`~`). For example, `(foo, ~Bar)` can be used to indicate that
+ * the type is related to the `foo` package but is not intended to match a static type.
+ */
+
+private import ApiGraphModelsSpecific as Specific
+
+private class Unit = Specific::Unit;
+
+private module API = Specific::API;
+
+private import Specific::AccessPathSyntax
+
+/** Module containing hooks for providing input data to be interpreted as a model. */
+module ModelInput {
+ /**
+ * A unit class for adding additional source model rows.
+ *
+ * Extend this class to add additional source definitions.
+ */
+ class SourceModelCsv extends Unit {
+ /**
+ * Holds if `row` specifies a source definition.
+ *
+ * A row of form
+ * ```
+ * package;type;path;kind
+ * ```
+ * indicates that the value at `(package, type, path)` should be seen as a flow
+ * source of the given `kind`.
+ *
+ * The kind `remote` represents a general remote flow source.
+ */
+ abstract predicate row(string row);
+ }
+
+ /**
+ * A unit class for adding additional sink model rows.
+ *
+ * Extend this class to add additional sink definitions.
+ */
+ class SinkModelCsv extends Unit {
+ /**
+ * Holds if `row` specifies a sink definition.
+ *
+ * A row of form
+ * ```
+ * package;type;path;kind
+ * ```
+ * indicates that the value at `(package, type, path)` should be seen as a sink
+ * of the given `kind`.
+ */
+ abstract predicate row(string row);
+ }
+
+ /**
+ * A unit class for adding additional summary model rows.
+ *
+ * Extend this class to add additional flow summary definitions.
+ */
+ class SummaryModelCsv extends Unit {
+ /**
+ * Holds if `row` specifies a summary definition.
+ *
+ * A row of form
+ * ```
+ * package;type;path;input;output;kind
+ * ```
+ * indicates that for each call to `(package, type, path)`, the value referred to by `input`
+ * can flow to the value referred to by `output`.
+ *
+ * `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
+ * respectively.
+ */
+ abstract predicate row(string row);
+ }
+
+ /**
+ * A unit class for adding additional type model rows.
+ *
+ * Extend this class to add additional type definitions.
+ */
+ class TypeModelCsv extends Unit {
+ /**
+ * Holds if `row` specifies a type definition.
+ *
+ * A row of form,
+ * ```
+ * package1;type1;package2;type2;path
+ * ```
+ * indicates that `(package2, type2, path)` should be seen as an instance of `(package1, type1)`.
+ */
+ abstract predicate row(string row);
+ }
+}
+
+private import ModelInput
+
+/**
+ * An empty class, except in specific tests.
+ *
+ * If this is non-empty, all models are parsed even if the package is not
+ * considered relevant for the current database.
+ */
+abstract class TestAllModels extends Unit { }
+
+/**
+ * Append `;dummy` to the value of `s` to work around the fact that `string.split(delim,n)`
+ * does not preserve empty trailing substrings.
+ */
+bindingset[result]
+private string inversePad(string s) { s = result + ";dummy" }
+
+private predicate sourceModel(string row) { any(SourceModelCsv s).row(inversePad(row)) }
+
+private predicate sinkModel(string row) { any(SinkModelCsv s).row(inversePad(row)) }
+
+private predicate summaryModel(string row) { any(SummaryModelCsv s).row(inversePad(row)) }
+
+private predicate typeModel(string row) { any(TypeModelCsv s).row(inversePad(row)) }
+
+/** Holds if a source model exists for the given parameters. */
+predicate sourceModel(string package, string type, string path, string kind) {
+ exists(string row |
+ sourceModel(row) and
+ row.splitAt(";", 0) = package and
+ row.splitAt(";", 1) = type and
+ row.splitAt(";", 2) = path and
+ row.splitAt(";", 3) = kind
+ )
+}
+
+/** Holds if a sink model exists for the given parameters. */
+private predicate sinkModel(string package, string type, string path, string kind) {
+ exists(string row |
+ sinkModel(row) and
+ row.splitAt(";", 0) = package and
+ row.splitAt(";", 1) = type and
+ row.splitAt(";", 2) = path and
+ row.splitAt(";", 3) = kind
+ )
+}
+
+/** Holds if a summary model `row` exists for the given parameters. */
+private predicate summaryModel(
+ string package, string type, string path, string input, string output, string kind
+) {
+ exists(string row |
+ summaryModel(row) and
+ row.splitAt(";", 0) = package and
+ row.splitAt(";", 1) = type and
+ row.splitAt(";", 2) = path and
+ row.splitAt(";", 3) = input and
+ row.splitAt(";", 4) = output and
+ row.splitAt(";", 5) = kind
+ )
+}
+
+/** Holds if an type model exists for the given parameters. */
+private predicate typeModel(
+ string package1, string type1, string package2, string type2, string path
+) {
+ exists(string row |
+ typeModel(row) and
+ row.splitAt(";", 0) = package1 and
+ row.splitAt(";", 1) = type1 and
+ row.splitAt(";", 2) = package2 and
+ row.splitAt(";", 3) = type2 and
+ row.splitAt(";", 4) = path
+ )
+}
+
+/**
+ * Gets a package that should be seen as an alias for the given other `package`,
+ * or the `package` itself.
+ */
+bindingset[package]
+bindingset[result]
+string getAPackageAlias(string package) {
+ typeModel(package, "", result, "", "")
+ or
+ result = package
+}
+
+/**
+ * Holds if CSV rows involving `package` might be relevant for the analysis of this database.
+ */
+private predicate isRelevantPackage(string package) {
+ (
+ sourceModel(package, _, _, _) or
+ sinkModel(package, _, _, _) or
+ summaryModel(package, _, _, _, _, _) or
+ typeModel(package, _, _, _, _)
+ ) and
+ (
+ Specific::isPackageUsed(package)
+ or
+ exists(TestAllModels t)
+ )
+ or
+ exists(string other |
+ isRelevantPackage(other) and
+ typeModel(package, _, other, _, _)
+ )
+}
+
+/**
+ * Holds if `package,type,path` is used in some CSV row.
+ */
+pragma[nomagic]
+predicate isRelevantFullPath(string package, string type, string path) {
+ isRelevantPackage(package) and
+ (
+ sourceModel(package, type, path, _) or
+ sinkModel(package, type, path, _) or
+ summaryModel(package, type, path, _, _, _) or
+ typeModel(_, _, package, type, path)
+ )
+}
+
+/** A string from a CSV row that should be parsed as an access path. */
+private class AccessPathRange extends AccessPath::Range {
+ AccessPathRange() {
+ isRelevantFullPath(_, _, this)
+ or
+ exists(string package | isRelevantPackage(package) |
+ summaryModel(package, _, _, this, _, _) or
+ summaryModel(package, _, _, _, this, _)
+ )
+ }
+}
+
+/**
+ * Gets a successor of `node` in the API graph.
+ */
+bindingset[token]
+API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
+ // API graphs use the same label for arguments and parameters. An edge originating from a
+ // use-node represents an argument, and an edge originating from a def-node represents a parameter.
+ // We just map both to the same thing.
+ token.getName() = ["Argument", "Parameter"] and
+ result = node.getParameter(AccessPath::parseIntUnbounded(token.getAnArgument()))
+ or
+ token.getName() = "ReturnValue" and
+ result = node.getReturn()
+ or
+ // Language-specific tokens
+ result = Specific::getExtraSuccessorFromNode(node, token)
+}
+
+/**
+ * Gets an API-graph successor for the given invocation.
+ */
+bindingset[token]
+API::Node getSuccessorFromInvoke(Specific::InvokeNode invoke, AccessPathToken token) {
+ token.getName() = "Argument" and
+ result =
+ invoke
+ .getParameter(AccessPath::parseIntWithArity(token.getAnArgument(), invoke.getNumArgument()))
+ or
+ token.getName() = "ReturnValue" and
+ result = invoke.getReturn()
+ or
+ // Language-specific tokens
+ result = Specific::getExtraSuccessorFromInvoke(invoke, token)
+}
+
+/**
+ * Holds if `invoke` invokes a call-site filter given by `token`.
+ */
+pragma[inline]
+private predicate invocationMatchesCallSiteFilter(Specific::InvokeNode invoke, AccessPathToken token) {
+ token.getName() = "WithArity" and
+ invoke.getNumArgument() = AccessPath::parseIntUnbounded(token.getAnArgument())
+ or
+ Specific::invocationMatchesExtraCallSiteFilter(invoke, token)
+}
+
+/**
+ * Gets the API node identified by the first `n` tokens of `path` in the given `(package, type, path)` tuple.
+ */
+pragma[nomagic]
+private API::Node getNodeFromPath(string package, string type, AccessPath path, int n) {
+ isRelevantFullPath(package, type, path) and
+ (
+ n = 0 and
+ exists(string package2, string type2, AccessPath path2 |
+ typeModel(package, type, package2, type2, path2) and
+ result = getNodeFromPath(package2, type2, path2, path2.getNumToken())
+ )
+ or
+ // Language-specific cases, such as handling of global variables
+ result = Specific::getExtraNodeFromPath(package, type, path, n)
+ )
+ or
+ result = getSuccessorFromNode(getNodeFromPath(package, type, path, n - 1), path.getToken(n - 1))
+ or
+ // Similar to the other recursive case, but where the path may have stepped through one or more call-site filters
+ result =
+ getSuccessorFromInvoke(getInvocationFromPath(package, type, path, n - 1), path.getToken(n - 1))
+}
+
+/** Gets the node identified by the given `(package, type, path)` tuple. */
+API::Node getNodeFromPath(string package, string type, AccessPath path) {
+ result = getNodeFromPath(package, type, path, path.getNumToken())
+}
+
+/**
+ * Gets an invocation identified by the given `(package, type, path)` tuple.
+ *
+ * Unlike `getNodeFromPath`, the `path` may end with one or more call-site filters.
+ */
+Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPath path, int n) {
+ result = Specific::getAnInvocationOf(getNodeFromPath(package, type, path, n))
+ or
+ result = getInvocationFromPath(package, type, path, n - 1) and
+ invocationMatchesCallSiteFilter(result, path.getToken(n - 1))
+}
+
+/** Gets an invocation identified by the given `(package, type, path)` tuple. */
+Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPath path) {
+ result = getInvocationFromPath(package, type, path, path.getNumToken())
+}
+
+/**
+ * Holds if `name` is a valid name for an access path token in the identifying access path.
+ */
+bindingset[name]
+predicate isValidTokenNameInIdentifyingAccessPath(string name) {
+ name = ["Argument", "Parameter", "ReturnValue", "WithArity"]
+ or
+ Specific::isExtraValidTokenNameInIdentifyingAccessPath(name)
+}
+
+/**
+ * Holds if `name` is a valid name for an access path token with no arguments, occurring
+ * in an identifying access path.
+ */
+bindingset[name]
+predicate isValidNoArgumentTokenInIdentifyingAccessPath(string name) {
+ name = "ReturnValue"
+ or
+ Specific::isExtraValidNoArgumentTokenInIdentifyingAccessPath(name)
+}
+
+/**
+ * Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
+ * in an identifying access path.
+ */
+bindingset[name, argument]
+predicate isValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
+ name = ["Argument", "Parameter"] and
+ argument.regexpMatch("(N-|-)?\\d+(\\.\\.((N-|-)?\\d+)?)?")
+ or
+ name = "WithArity" and
+ argument.regexpMatch("\\d+(\\.\\.(\\d+)?)?")
+ or
+ Specific::isExtraValidTokenArgumentInIdentifyingAccessPath(name, argument)
+}
+
+/**
+ * Module providing access to the imported models in terms of API graph nodes.
+ */
+module ModelOutput {
+ /**
+ * Holds if a CSV source model contributed `source` with the given `kind`.
+ */
+ API::Node getASourceNode(string kind) {
+ exists(string package, string type, string path |
+ sourceModel(package, type, path, kind) and
+ result = getNodeFromPath(package, type, path)
+ )
+ }
+
+ /**
+ * Holds if a CSV sink model contributed `sink` with the given `kind`.
+ */
+ API::Node getASinkNode(string kind) {
+ exists(string package, string type, string path |
+ sinkModel(package, type, path, kind) and
+ result = getNodeFromPath(package, type, path)
+ )
+ }
+
+ /**
+ * Holds if a relevant CSV summary exists for these parameters.
+ */
+ predicate relevantSummaryModel(
+ string package, string type, string path, string input, string output, string kind
+ ) {
+ isRelevantPackage(package) and
+ summaryModel(package, type, path, input, output, kind)
+ }
+
+ /**
+ * Holds if a `baseNode` is an invocation identified by the `package,type,path` part of a summary row.
+ */
+ predicate resolvedSummaryBase(
+ string package, string type, string path, Specific::InvokeNode baseNode
+ ) {
+ summaryModel(package, type, path, _, _, _) and
+ baseNode = getInvocationFromPath(package, type, path)
+ }
+
+ /**
+ * Holds if `node` is seen as an instance of `(package,type)` due to a type definition
+ * contributed by a CSV model.
+ */
+ API::Node getATypeNode(string package, string type) {
+ exists(string package2, string type2, AccessPath path |
+ typeModel(package, type, package2, type2, path) and
+ result = getNodeFromPath(package2, type2, path)
+ )
+ }
+
+ /**
+ * Gets an error message relating to an invalid CSV row in a model.
+ */
+ string getAWarning() {
+ // Check number of columns
+ exists(string row, string kind, int expectedArity, int actualArity |
+ any(SourceModelCsv csv).row(row) and kind = "source" and expectedArity = 4
+ or
+ any(SinkModelCsv csv).row(row) and kind = "sink" and expectedArity = 4
+ or
+ any(SummaryModelCsv csv).row(row) and kind = "summary" and expectedArity = 6
+ or
+ any(TypeModelCsv csv).row(row) and kind = "type" and expectedArity = 5
+ |
+ actualArity = count(row.indexOf(";")) + 1 and
+ actualArity != expectedArity and
+ result =
+ "CSV " + kind + " row should have " + expectedArity + " columns but has " + actualArity +
+ ": " + row
+ )
+ or
+ // Check names and arguments of access path tokens
+ exists(AccessPath path, AccessPathToken token |
+ isRelevantFullPath(_, _, path) and
+ token = path.getToken(_)
+ |
+ not isValidTokenNameInIdentifyingAccessPath(token.getName()) and
+ result = "Invalid token name '" + token.getName() + "' in access path: " + path
+ or
+ isValidTokenNameInIdentifyingAccessPath(token.getName()) and
+ exists(string argument |
+ argument = token.getAnArgument() and
+ not isValidTokenArgumentInIdentifyingAccessPath(token.getName(), argument) and
+ result =
+ "Invalid argument '" + argument + "' in token '" + token + "' in access path: " + path
+ )
+ or
+ isValidTokenNameInIdentifyingAccessPath(token.getName()) and
+ token.getNumArgument() = 0 and
+ not isValidNoArgumentTokenInIdentifyingAccessPath(token.getName()) and
+ result = "Invalid token '" + token + "' is missing its arguments, in access path: " + path
+ )
+ }
+}
diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll
new file mode 100644
index 00000000000..92f7dcbd50b
--- /dev/null
+++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -0,0 +1,202 @@
+/**
+ * Contains the language-specific part of the models-as-data implementation found in `ApiGraphModels.qll`.
+ *
+ * It must export the following members:
+ * ```ql
+ * class Unit // a unit type
+ * module AccessPathSyntax // a re-export of the AccessPathSyntax module
+ * class InvokeNode // a type representing an invocation connected to the API graph
+ * module API // the API graph module
+ * predicate isPackageUsed(string package)
+ * API::Node getExtraNodeFromPath(string package, string type, string path, int n)
+ * API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token)
+ * API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken token)
+ * predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPathToken token)
+ * InvokeNode getAnInvocationOf(API::Node node)
+ * predicate isExtraValidTokenNameInIdentifyingAccessPath(string name)
+ * predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name)
+ * predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument)
+ * ```
+ */
+
+private import python as PY
+private import semmle.python.dataflow.new.DataFlow
+private import ApiGraphModels
+import semmle.python.ApiGraphs::API as API
+
+class Unit = PY::Unit;
+
+// Re-export libraries needed by ApiGraphModels.qll
+import semmle.python.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
+private import AccessPathSyntax
+
+/**
+ * Holds if models describing `package` may be relevant for the analysis of this database.
+ */
+predicate isPackageUsed(string package) { exists(API::moduleImport(package)) }
+
+/** Gets a Python-specific interpretation of the `(package, type, path)` tuple after resolving the first `n` access path tokens. */
+bindingset[package, type, path]
+API::Node getExtraNodeFromPath(string package, string type, AccessPath path, int n) {
+ type = "" and
+ n = 0 and
+ result = API::moduleImport(package) and
+ exists(path)
+}
+
+/**
+ * Gets a Python-specific API graph successor of `node` reachable by resolving `token`.
+ */
+bindingset[token]
+API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token) {
+ token.getName() = "Member" and
+ result = node.getMember(token.getAnArgument())
+ or
+ token.getName() = "Instance" and
+ result = node.getReturn() // In Python `Instance` is just an alias for `ReturnValue`
+ or
+ token.getName() = "Awaited" and
+ result = node.getAwaited()
+ or
+ token.getName() = "Subclass" and
+ result = node.getASubclass*()
+ or
+ token.getName() = "Method" and
+ result = node.getMember(token.getAnArgument()).getReturn()
+ or
+ token.getName() = ["Argument", "Parameter"] and
+ (
+ token.getAnArgument() = "self" and
+ result = node.getSelfParameter()
+ or
+ exists(string name | token.getAnArgument() = name + ":" |
+ result = node.getKeywordParameter(name)
+ )
+ or
+ token.getAnArgument() = "any" and
+ result = [node.getParameter(_), node.getKeywordParameter(_)]
+ or
+ token.getAnArgument() = "any-named" and
+ result = node.getKeywordParameter(_)
+ )
+ // Some features don't have MaD tokens yet, they would need to be added to API-graphs first.
+ // - decorators ("DecoratedClass", "DecoratedMember", "DecoratedParameter")
+ // - Array/Map elements ("ArrayElement", "Element", "MapKey", "MapValue")
+}
+
+/**
+ * Gets a Python-specific API graph successor of `node` reachable by resolving `token`.
+ */
+bindingset[token]
+API::Node getExtraSuccessorFromInvoke(API::CallNode node, AccessPathToken token) {
+ token.getName() = "Instance" and
+ result = node.getReturn()
+ or
+ token.getName() = ["Argument", "Parameter"] and
+ (
+ token.getAnArgument() = "self" and
+ result = node.getSelfParameter()
+ or
+ token.getAnArgument() = "any" and
+ result = [node.getParameter(_), node.getKeywordParameter(_)]
+ or
+ token.getAnArgument() = "any-named" and
+ result = node.getKeywordParameter(_)
+ or
+ exists(string arg | arg + ":" = token.getAnArgument() | result = node.getKeywordParameter(arg))
+ )
+}
+
+/**
+ * Holds if `invoke` matches the PY-specific call site filter in `token`.
+ */
+bindingset[token]
+predicate invocationMatchesExtraCallSiteFilter(API::CallNode invoke, AccessPathToken token) {
+ token.getName() = "Call" and exists(invoke) // there is only one kind of call in Python.
+}
+
+/**
+ * Holds if `path` is an input or output spec for a summary with the given `base` node.
+ */
+pragma[nomagic]
+private predicate relevantInputOutputPath(API::CallNode base, AccessPath inputOrOutput) {
+ exists(string package, string type, string input, string output, string path |
+ ModelOutput::relevantSummaryModel(package, type, path, input, output, _) and
+ ModelOutput::resolvedSummaryBase(package, type, path, base) and
+ inputOrOutput = [input, output]
+ )
+}
+
+/**
+ * Gets the API node for the first `n` tokens of the given input/output path, evaluated relative to `baseNode`.
+ */
+private API::Node getNodeFromInputOutputPath(API::CallNode baseNode, AccessPath path, int n) {
+ relevantInputOutputPath(baseNode, path) and
+ (
+ n = 1 and
+ result = getSuccessorFromInvoke(baseNode, path.getToken(0))
+ or
+ result =
+ getSuccessorFromNode(getNodeFromInputOutputPath(baseNode, path, n - 1), path.getToken(n - 1))
+ )
+}
+
+/**
+ * Gets the API node for the given input/output path, evaluated relative to `baseNode`.
+ */
+private API::Node getNodeFromInputOutputPath(API::CallNode baseNode, AccessPath path) {
+ result = getNodeFromInputOutputPath(baseNode, path, path.getNumToken())
+}
+
+/**
+ * Holds if a CSV summary contributed the step `pred -> succ` of the given `kind`.
+ */
+predicate summaryStep(API::Node pred, API::Node succ, string kind) {
+ exists(
+ string package, string type, string path, API::CallNode base, AccessPath input,
+ AccessPath output
+ |
+ ModelOutput::relevantSummaryModel(package, type, path, input, output, kind) and
+ ModelOutput::resolvedSummaryBase(package, type, path, base) and
+ pred = getNodeFromInputOutputPath(base, input) and
+ succ = getNodeFromInputOutputPath(base, output)
+ )
+}
+
+class InvokeNode = API::CallNode;
+
+/** Gets an `InvokeNode` corresponding to an invocation of `node`. */
+InvokeNode getAnInvocationOf(API::Node node) { result = node.getACall() }
+
+/**
+ * Holds if `name` is a valid name for an access path token in the identifying access path.
+ */
+bindingset[name]
+predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
+ name = ["Member", "Instance", "Awaited", "Call", "Method", "Subclass"]
+}
+
+/**
+ * Holds if `name` is a valid name for an access path token with no arguments, occurring
+ * in an identifying access path.
+ */
+predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name) {
+ name = ["Instance", "Awaited", "Call", "Subclass"]
+}
+
+/**
+ * Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
+ * in an identifying access path.
+ */
+bindingset[name, argument]
+predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
+ name = ["Member", "Method"] and
+ exists(argument)
+ or
+ name = ["Argument", "Parameter"] and
+ (
+ argument = ["self", "any", "any-named"]
+ or
+ argument.regexpMatch("\\w+:") // keyword argument
+ )
+}
diff --git a/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll
index 410eee50b29..5a033664823 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll
@@ -59,6 +59,12 @@ module PathInjection {
FileSystemAccessAsSink() { this = any(FileSystemAccess e).getAPathArgument() }
}
+ private import semmle.python.frameworks.data.ModelsAsData
+
+ private class DataAsFileSink extends Sink {
+ DataAsFileSink() { this = ModelOutput::getASinkNode("path-injection").getARhs() }
+ }
+
/**
* A comparison with a constant string, considered as a sanitizer-guard.
*/
diff --git a/python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll
index 756a1f6b773..cf21a5c0e94 100644
--- a/python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll
@@ -60,4 +60,11 @@ module SqlInjection {
* A comparison with a constant string, considered as a sanitizer-guard.
*/
class StringConstCompareAsSanitizerGuard extends SanitizerGuard, StringConstCompare { }
+
+ private import semmle.python.frameworks.data.ModelsAsData
+
+ /** A sink for sql-injection from model data. */
+ private class DataAsSqlSink extends Sink {
+ DataAsSqlSink() { this = ModelOutput::getASinkNode("sql-injection").getARhs() }
+ }
}
diff --git a/python/ql/test/experimental/meta/MaDTest.qll b/python/ql/test/experimental/meta/MaDTest.qll
new file mode 100644
index 00000000000..345fc973284
--- /dev/null
+++ b/python/ql/test/experimental/meta/MaDTest.qll
@@ -0,0 +1,46 @@
+import python
+private import semmle.python.dataflow.new.DataFlow
+private import semmle.python.dataflow.new.internal.PrintNode
+private import semmle.python.frameworks.data.ModelsAsData
+// need to import Frameworks to get the actual modeling imported
+private import semmle.python.Frameworks
+// this import needs to be public to get the query predicates propagated to the actual test files
+import TestUtilities.InlineExpectationsTest
+
+class MadSinkTest extends InlineExpectationsTest {
+ MadSinkTest() { this = "MadSinkTest" }
+
+ override string getARelevantTag() {
+ exists(string kind | exists(ModelOutput::getASinkNode(kind)) | result = "mad-sink__" + kind)
+ }
+
+ override predicate hasActualResult(Location location, string element, string tag, string value) {
+ exists(location.getFile().getRelativePath()) and
+ exists(DataFlow::Node sink, string kind |
+ sink = ModelOutput::getASinkNode(kind).getARhs() and
+ location = sink.getLocation() and
+ element = sink.toString() and
+ value = prettyNodeForInlineTest(sink) and
+ tag = "mad-sink__" + kind
+ )
+ }
+}
+
+class MadSourceTest extends InlineExpectationsTest {
+ MadSourceTest() { this = "MadSourceTest" }
+
+ override string getARelevantTag() {
+ exists(string kind | exists(ModelOutput::getASourceNode(kind)) | result = "mad-source__" + kind)
+ }
+
+ override predicate hasActualResult(Location location, string element, string tag, string value) {
+ exists(location.getFile().getRelativePath()) and
+ exists(DataFlow::Node source, string kind |
+ source = ModelOutput::getASourceNode(kind).getAnImmediateUse() and
+ location = source.getLocation() and
+ element = source.toString() and
+ value = prettyNodeForInlineTest(source) and
+ tag = "mad-source__" + kind
+ )
+ }
+}
diff --git a/python/ql/test/library-tests/frameworks/asyncpg/MaDTest.expected b/python/ql/test/library-tests/frameworks/asyncpg/MaDTest.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/python/ql/test/library-tests/frameworks/asyncpg/MaDTest.ql b/python/ql/test/library-tests/frameworks/asyncpg/MaDTest.ql
new file mode 100644
index 00000000000..fef4356ab35
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/asyncpg/MaDTest.ql
@@ -0,0 +1,2 @@
+import python
+import experimental.meta.MaDTest
diff --git a/python/ql/test/library-tests/frameworks/asyncpg/test.py b/python/ql/test/library-tests/frameworks/asyncpg/test.py
index e4b3c895ece..e2e5e1c5826 100644
--- a/python/ql/test/library-tests/frameworks/asyncpg/test.py
+++ b/python/ql/test/library-tests/frameworks/asyncpg/test.py
@@ -7,17 +7,17 @@ async def test_connection():
try:
# The file-like object is passed in as a keyword-only argument.
# See https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.connection.Connection.copy_from_query
- await conn.copy_from_query("sql", output="filepath") # $ getSql="sql" getAPathArgument="filepath"
- await conn.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ getSql="sql" getAPathArgument="filepath"
+ await conn.copy_from_query("sql", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
+ await conn.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
- await conn.copy_from_table("table", output="filepath") # $ getAPathArgument="filepath"
- await conn.copy_to_table("table", source="filepath") # $ getAPathArgument="filepath"
+ await conn.copy_from_table("table", output="filepath") # $ mad-sink__path-injection="filepath"
+ await conn.copy_to_table("table", source="filepath") # $ mad-sink__path-injection="filepath"
- await conn.execute("sql") # $ getSql="sql"
- await conn.executemany("sql") # $ getSql="sql"
- await conn.fetch("sql") # $ getSql="sql"
- await conn.fetchrow("sql") # $ getSql="sql"
- await conn.fetchval("sql") # $ getSql="sql"
+ await conn.execute("sql") # $ mad-sink__sql-injection="sql"
+ await conn.executemany("sql") # $ mad-sink__sql-injection="sql"
+ await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
+ await conn.fetchrow("sql") # $ mad-sink__sql-injection="sql"
+ await conn.fetchval("sql") # $ mad-sink__sql-injection="sql"
finally:
await conn.close()
@@ -27,11 +27,11 @@ async def test_prepared_statement():
conn = await asyncpg.connect()
try:
- pstmt = await conn.prepare("psql") # $ constructedSql="psql"
- pstmt.executemany() # $ getSql="psql"
- pstmt.fetch() # $ getSql="psql"
- pstmt.fetchrow() # $ getSql="psql"
- pstmt.fetchval() # $ getSql="psql"
+ pstmt = await conn.prepare("psql") # $ mad-sink__sql-injection="psql"
+ pstmt.executemany()
+ pstmt.fetch()
+ pstmt.fetchrow()
+ pstmt.fetchval()
finally:
await conn.close()
@@ -46,7 +46,7 @@ async def test_cursor():
cursor = await conn.cursor("sql") # $ getSql="sql" constructedSql="sql"
await cursor.fetch()
- pstmt = await conn.prepare("psql") # $ constructedSql="psql"
+ pstmt = await conn.prepare("psql") # $ mad-sink__sql-injection="psql"
pcursor = await pstmt.cursor() # $ getSql="psql"
await pcursor.fetch()
@@ -69,23 +69,23 @@ async def test_connection_pool():
pool = await asyncpg.create_pool()
try:
- await pool.copy_from_query("sql", output="filepath") # $ getSql="sql" getAPathArgument="filepath"
- await pool.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ getSql="sql" getAPathArgument="filepath"
- await pool.copy_from_table("table", output="filepath") # $ getAPathArgument="filepath"
- await pool.copy_to_table("table", source="filepath") # $ getAPathArgument="filepath"
+ await pool.copy_from_query("sql", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
+ await pool.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
+ await pool.copy_from_table("table", output="filepath") # $ mad-sink__path-injection="filepath"
+ await pool.copy_to_table("table", source="filepath") # $ mad-sink__path-injection="filepath"
- await pool.execute("sql") # $ getSql="sql"
- await pool.executemany("sql") # $ getSql="sql"
- await pool.fetch("sql") # $ getSql="sql"
- await pool.fetchrow("sql") # $ getSql="sql"
- await pool.fetchval("sql") # $ getSql="sql"
+ await pool.execute("sql") # $ mad-sink__sql-injection="sql"
+ await pool.executemany("sql") # $ mad-sink__sql-injection="sql"
+ await pool.fetch("sql") # $ mad-sink__sql-injection="sql"
+ await pool.fetchrow("sql") # $ mad-sink__sql-injection="sql"
+ await pool.fetchval("sql") # $ mad-sink__sql-injection="sql"
async with pool.acquire() as conn:
- await conn.execute("sql") # $ getSql="sql"
+ await conn.execute("sql") # $ mad-sink__sql-injection="sql"
conn = await pool.acquire()
try:
- await conn.fetch("sql") # $ getSql="sql"
+ await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
finally:
await pool.release(conn)
@@ -93,13 +93,13 @@ async def test_connection_pool():
await pool.close()
async with asyncpg.create_pool() as pool:
- await pool.execute("sql") # $ getSql="sql"
+ await pool.execute("sql") # $ mad-sink__sql-injection="sql"
async with pool.acquire() as conn:
- await conn.execute("sql") # $ getSql="sql"
+ await conn.execute("sql") # $ mad-sink__sql-injection="sql"
conn = await pool.acquire()
try:
- await conn.fetch("sql") # $ getSql="sql"
+ await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
finally:
await pool.release(conn)
diff --git a/python/ql/test/library-tests/frameworks/data/test.expected b/python/ql/test/library-tests/frameworks/data/test.expected
new file mode 100644
index 00000000000..68de6ecd878
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/data/test.expected
@@ -0,0 +1,103 @@
+taintFlow
+| test.py:3:5:3:15 | ControlFlowNode for getSource() | test.py:4:8:4:8 | ControlFlowNode for x |
+| test.py:3:5:3:15 | ControlFlowNode for getSource() | test.py:7:17:7:17 | ControlFlowNode for x |
+| test.py:9:8:9:14 | ControlFlowNode for alias() | test.py:9:8:9:14 | ControlFlowNode for alias() |
+| test.py:10:8:10:22 | ControlFlowNode for Attribute() | test.py:10:8:10:22 | ControlFlowNode for Attribute() |
+| test.py:11:8:11:30 | ControlFlowNode for Attribute() | test.py:11:8:11:30 | ControlFlowNode for Attribute() |
+| test.py:71:28:71:38 | ControlFlowNode for getSource() | test.py:71:8:71:39 | ControlFlowNode for Attribute() |
+| test.py:75:5:75:15 | ControlFlowNode for getSource() | test.py:76:22:76:22 | ControlFlowNode for x |
+| test.py:75:5:75:15 | ControlFlowNode for getSource() | test.py:77:22:77:22 | ControlFlowNode for y |
+| test.py:81:36:81:46 | ControlFlowNode for getSource() | test.py:81:8:81:47 | ControlFlowNode for Attribute() |
+| test.py:83:50:83:60 | ControlFlowNode for getSource() | test.py:83:8:83:61 | ControlFlowNode for Attribute() |
+| test.py:86:49:86:59 | ControlFlowNode for getSource() | test.py:86:8:86:60 | ControlFlowNode for Attribute() |
+| test.py:87:56:87:66 | ControlFlowNode for getSource() | test.py:87:8:87:67 | ControlFlowNode for Attribute() |
+isSink
+| test.py:4:8:4:8 | ControlFlowNode for x | test-sink |
+| test.py:7:17:7:17 | ControlFlowNode for x | test-sink |
+| test.py:9:8:9:14 | ControlFlowNode for alias() | test-sink |
+| test.py:10:8:10:22 | ControlFlowNode for Attribute() | test-sink |
+| test.py:11:8:11:30 | ControlFlowNode for Attribute() | test-sink |
+| test.py:12:8:12:34 | ControlFlowNode for Attribute() | test-sink |
+| test.py:16:11:16:13 | ControlFlowNode for one | test-sink |
+| test.py:17:19:17:21 | ControlFlowNode for two | test-sink |
+| test.py:17:24:17:28 | ControlFlowNode for three | test-sink |
+| test.py:17:31:17:34 | ControlFlowNode for four | test-sink |
+| test.py:18:37:18:40 | ControlFlowNode for five | test-sink |
+| test.py:19:21:19:26 | ControlFlowNode for second | test-sink |
+| test.py:30:21:30:23 | ControlFlowNode for one | test-sink |
+| test.py:32:22:32:24 | ControlFlowNode for one | test-sink |
+| test.py:32:27:32:29 | ControlFlowNode for two | test-sink |
+| test.py:33:22:33:24 | ControlFlowNode for one | test-sink |
+| test.py:33:27:33:29 | ControlFlowNode for two | test-sink |
+| test.py:33:32:33:36 | ControlFlowNode for three | test-sink |
+| test.py:57:27:57:33 | ControlFlowNode for arg_pos | test-sink |
+| test.py:66:17:66:20 | ControlFlowNode for arg1 | test-sink |
+| test.py:66:23:66:26 | ControlFlowNode for arg2 | test-sink |
+| test.py:66:34:66:43 | ControlFlowNode for namedThing | test-sink |
+| test.py:67:34:67:44 | ControlFlowNode for secondNamed | test-sink |
+| test.py:71:8:71:39 | ControlFlowNode for Attribute() | test-sink |
+| test.py:72:8:72:47 | ControlFlowNode for Attribute() | test-sink |
+| test.py:76:22:76:22 | ControlFlowNode for x | test-sink |
+| test.py:77:22:77:22 | ControlFlowNode for y | test-sink |
+| test.py:78:22:78:22 | ControlFlowNode for z | test-sink |
+| test.py:81:8:81:47 | ControlFlowNode for Attribute() | test-sink |
+| test.py:82:8:82:54 | ControlFlowNode for Attribute() | test-sink |
+| test.py:83:8:83:61 | ControlFlowNode for Attribute() | test-sink |
+| test.py:85:8:85:53 | ControlFlowNode for Attribute() | test-sink |
+| test.py:86:8:86:60 | ControlFlowNode for Attribute() | test-sink |
+| test.py:87:8:87:67 | ControlFlowNode for Attribute() | test-sink |
+| test.py:89:21:89:23 | ControlFlowNode for one | test-sink |
+| test.py:91:21:91:23 | ControlFlowNode for one | test-sink |
+| test.py:91:30:91:32 | ControlFlowNode for two | test-sink |
+| test.py:98:6:98:9 | ControlFlowNode for baz2 | test-sink |
+isSource
+| test.py:3:5:3:15 | ControlFlowNode for getSource() | test-source |
+| test.py:9:8:9:14 | ControlFlowNode for alias() | test-source |
+| test.py:10:8:10:14 | ControlFlowNode for alias() | test-source |
+| test.py:10:8:10:22 | ControlFlowNode for Attribute() | test-source |
+| test.py:11:8:11:14 | ControlFlowNode for alias() | test-source |
+| test.py:11:8:11:22 | ControlFlowNode for Attribute() | test-source |
+| test.py:11:8:11:30 | ControlFlowNode for Attribute() | test-source |
+| test.py:12:8:12:14 | ControlFlowNode for alias() | test-source |
+| test.py:12:8:12:22 | ControlFlowNode for Attribute() | test-source |
+| test.py:23:24:23:26 | ControlFlowNode for one | test-source |
+| test.py:24:33:24:35 | ControlFlowNode for two | test-source |
+| test.py:24:38:24:42 | ControlFlowNode for three | test-source |
+| test.py:24:45:24:48 | ControlFlowNode for four | test-source |
+| test.py:25:34:25:39 | ControlFlowNode for second | test-source |
+| test.py:39:11:39:20 | ControlFlowNode for Await | test-source |
+| test.py:41:8:41:27 | ControlFlowNode for Attribute() | test-source |
+| test.py:46:7:46:16 | ControlFlowNode for SubClass() | test-source |
+| test.py:53:7:53:16 | ControlFlowNode for Attribute() | test-source |
+| test.py:60:13:60:16 | ControlFlowNode for self | test-source |
+| test.py:60:24:60:28 | ControlFlowNode for named | test-source |
+| test.py:63:36:63:39 | ControlFlowNode for arg2 | test-source |
+| test.py:63:42:63:45 | ControlFlowNode for arg3 | test-source |
+| test.py:63:48:63:51 | ControlFlowNode for arg4 | test-source |
+| test.py:63:54:63:57 | ControlFlowNode for arg5 | test-source |
+| test.py:71:28:71:38 | ControlFlowNode for getSource() | test-source |
+| test.py:72:36:72:46 | ControlFlowNode for getSource() | test-source |
+| test.py:75:5:75:15 | ControlFlowNode for getSource() | test-source |
+| test.py:81:36:81:46 | ControlFlowNode for getSource() | test-source |
+| test.py:82:43:82:53 | ControlFlowNode for getSource() | test-source |
+| test.py:83:50:83:60 | ControlFlowNode for getSource() | test-source |
+| test.py:85:42:85:52 | ControlFlowNode for getSource() | test-source |
+| test.py:86:49:86:59 | ControlFlowNode for getSource() | test-source |
+| test.py:87:56:87:66 | ControlFlowNode for getSource() | test-source |
+| test.py:101:29:101:31 | ControlFlowNode for arg | test-source |
+| test.py:104:24:104:29 | ControlFlowNode for param1 | test-source |
+| test.py:104:32:104:37 | ControlFlowNode for param2 | test-source |
+| test.py:107:24:107:28 | ControlFlowNode for name1 | test-source |
+| test.py:107:31:107:35 | ControlFlowNode for name2 | test-source |
+syntaxErrors
+| Member[foo |
+| Member[foo] .Member[bar] |
+| Member[foo] Member[bar] |
+| Member[foo], Member[bar] |
+| Member[foo],Member[bar] |
+| Member[foo]. Member[bar] |
+| Member[foo]..Member[bar] |
+| Member[foo]Member[bar] |
+| Member[foo]] |
+| Member[foo]].Member[bar] |
+warning
diff --git a/python/ql/test/library-tests/frameworks/data/test.py b/python/ql/test/library-tests/frameworks/data/test.py
new file mode 100644
index 00000000000..ea1a6e0d4d4
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/data/test.py
@@ -0,0 +1,108 @@
+from testlib import getSource, mySink, alias
+
+x = getSource()
+mySink(x)
+
+mySink(foo=x) # OK
+mySink(sinkName=x) # NOT OK
+
+mySink(alias()) # NOT OK
+mySink(alias().chain()) # NOT OK
+mySink(alias().chain().chain()) # NOT OK
+mySink(alias().chain().safeThing()) # OK
+
+from testlib import Args
+
+Args.arg0(one, two, three, four, five)
+Args.arg1to3(one, two, three, four, five)
+Args.lastarg(one, two, three, four, five)
+Args.nonFist(first, second)
+
+from testlib import Callbacks
+
+Callbacks.first(lambda one, two, three, four, five: 0)
+Callbacks.param1to3(lambda one, two, three, four, five: 0)
+Callbacks.nonFirst(lambda first, second: 0)
+
+from testlib import CallFilter
+
+CallFilter.arityOne(one, two) # NO match
+CallFilter.arityOne(one) # Match
+CallFilter.twoOrMore(one) # NO match
+CallFilter.twoOrMore(one, two) # Match
+CallFilter.twoOrMore(one, two, three) # Match
+
+from testlib import CommonTokens
+
+async def async_func():
+ prom = CommonTokens.makePromise(1);
+ val = await prom
+
+inst = CommonTokens.Class()
+
+class SubClass (CommonTokens.Super):
+ pass
+
+sub = SubClass()
+
+class Sub2Class (CommonTokens.Class):
+ pass
+
+sub2 = Sub2Class() # TODO: Currently not recognized as an instance of CommonTokens.Class
+
+val = inst.foo()
+
+from testlib import ArgPos
+
+arg_pos = ArgPos(); val = arg_pos.self_thing(arg, named=2);
+
+class SubClass (ArgPos.MyClass):
+ def foo(self, arg, named=2, otherName=3):
+ pass
+
+ def secondAndAfter(self, arg1, arg2, arg3, arg4, arg5):
+ pass
+
+ArgPos.anyParam(arg1, arg2, name=namedThing)
+ArgPos.anyNamed(arg4, arg5, name=secondNamed)
+
+from testlib import Steps
+
+mySink(Steps.preserveTaint(getSource())) # FLOW
+mySink(Steps.preserveTaint("safe", getSource())) # NO FLOW
+
+Steps.taintIntoCallback(
+ getSource(),
+ lambda x: mySink(x), # FLOW
+ lambda y: mySink(y), # FLOW
+ lambda z: mySink(z) # NO FLOW
+)
+
+mySink(Steps.preserveArgZeroAndTwo(getSource())) # FLOW
+mySink(Steps.preserveArgZeroAndTwo("foo", getSource())) # NO FLOW
+mySink(Steps.preserveArgZeroAndTwo("foo", "bar", getSource())) # FLOW
+
+mySink(Steps.preserveAllButFirstArgument(getSource())) # NO FLOW
+mySink(Steps.preserveAllButFirstArgument("foo", getSource())) # FLOW
+mySink(Steps.preserveAllButFirstArgument("foo", "bar", getSource())) # FLOW
+
+CallFilter.arityOne(one) # match
+CallFilter.arityOne(one=one) # NO match
+CallFilter.arityOne(one, two=two) # match - on both the named and positional arguments
+CallFilter.arityOne(one=one, two=two) # NO match
+
+from foo1.bar import baz1
+baz1(baz1) # no match, and that's the point.
+
+from foo2.bar import baz2
+baz2(baz2) # match
+
+class OtherSubClass (ArgPos.MyClass):
+ def otherSelfTest(self, arg, named=2, otherName=3): # test that Parameter[0] hits `arg`.
+ pass
+
+ def anyParam(self, param1, param2): # Parameter[any] matches all non-self parameters
+ pass
+
+ def anyNamed(self, name1, name2=2): # Parameter[any-named] matches all non-self named parameters
+ pass
diff --git a/python/ql/test/library-tests/frameworks/data/test.ql b/python/ql/test/library-tests/frameworks/data/test.ql
new file mode 100644
index 00000000000..86f960b1adf
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/data/test.ql
@@ -0,0 +1,127 @@
+import python
+import semmle.python.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
+import semmle.python.frameworks.data.ModelsAsData
+import semmle.python.dataflow.new.TaintTracking
+import semmle.python.dataflow.new.DataFlow
+private import semmle.python.ApiGraphs
+
+class Steps extends ModelInput::SummaryModelCsv {
+ override predicate row(string row) {
+ // package;type;path;input;output;kind
+ row =
+ [
+ "testlib;;Member[Steps].Member[preserveTaint].Call;Argument[0];ReturnValue;taint",
+ "testlib;;Member[Steps].Member[taintIntoCallback];Argument[0];Argument[1..2].Parameter[0];taint",
+ "testlib;;Member[Steps].Member[preserveArgZeroAndTwo];Argument[0,2];ReturnValue;taint",
+ "testlib;;Member[Steps].Member[preserveAllButFirstArgument].Call;Argument[1..];ReturnValue;taint",
+ ]
+ }
+}
+
+class Types extends ModelInput::TypeModelCsv {
+ override predicate row(string row) {
+ // package1;type1;package2;type2;path
+ row =
+ [
+ "testlib;Alias;testlib;;Member[alias].ReturnValue",
+ "testlib;Alias;testlib;Alias;Member[chain].ReturnValue",
+ ]
+ }
+}
+
+class Sinks extends ModelInput::SinkModelCsv {
+ override predicate row(string row) {
+ // package;type;path;kind
+ row =
+ [
+ "testlib;;Member[mySink].Argument[0,sinkName:];test-sink",
+ // testing argument syntax
+ "testlib;;Member[Args].Member[arg0].Argument[0];test-sink", //
+ "testlib;;Member[Args].Member[arg1to3].Argument[1..3];test-sink", //
+ "testlib;;Member[Args].Member[lastarg].Argument[N-1];test-sink", //
+ "testlib;;Member[Args].Member[nonFist].Argument[1..];test-sink", //
+ // callsite filter.
+ "testlib;;Member[CallFilter].Member[arityOne].WithArity[1].Argument[any];test-sink", //
+ "testlib;;Member[CallFilter].Member[twoOrMore].WithArity[2..].Argument[0..];test-sink", //
+ // testing non-positional arguments
+ "testlib;;Member[ArgPos].Instance.Member[self_thing].Argument[self];test-sink", //
+ // any argument
+ "testlib;;Member[ArgPos].Member[anyParam].Argument[any];test-sink", //
+ "testlib;;Member[ArgPos].Member[anyNamed].Argument[any-named];test-sink", //
+ // testing package syntax
+ "foo1.bar;;Member[baz1].Argument[any];test-sink", //
+ "foo2;;Member[bar].Member[baz2].Argument[any];test-sink", //
+ ]
+ }
+}
+
+class Sources extends ModelInput::SourceModelCsv {
+ // package;type;path;kind
+ override predicate row(string row) {
+ row =
+ [
+ "testlib;;Member[getSource].ReturnValue;test-source", //
+ "testlib;Alias;;test-source",
+ // testing parameter syntax
+ "testlib;;Member[Callbacks].Member[first].Argument[0].Parameter[0];test-source", //
+ "testlib;;Member[Callbacks].Member[param1to3].Argument[0].Parameter[1..3];test-source", //
+ "testlib;;Member[Callbacks].Member[nonFirst].Argument[0].Parameter[1..];test-source", //
+ // Common tokens.
+ "testlib;;Member[CommonTokens].Member[makePromise].ReturnValue.Awaited;test-source", //
+ "testlib;;Member[CommonTokens].Member[Class].Instance;test-source", //
+ "testlib;;Member[CommonTokens].Member[Super].Subclass.Instance;test-source", //
+ // method
+ "testlib;;Member[CommonTokens].Member[Class].Instance.Method[foo];test-source", //
+ // testing non-positional arguments
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[self];test-source", //
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[foo].Parameter[named:];test-source", //
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[secondAndAfter].Parameter[1..];test-source", //
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[otherSelfTest].Parameter[0];test-source", //
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[anyParam].Parameter[any];test-source", //
+ "testlib;;Member[ArgPos].Member[MyClass].Subclass.Member[anyNamed].Parameter[any-named];test-source", //
+ ]
+ }
+}
+
+class BasicTaintTracking extends TaintTracking::Configuration {
+ BasicTaintTracking() { this = "BasicTaintTracking" }
+
+ override predicate isSource(DataFlow::Node source) {
+ source = ModelOutput::getASourceNode("test-source").getAnImmediateUse()
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ sink = ModelOutput::getASinkNode("test-sink").getARhs()
+ }
+}
+
+query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
+ any(BasicTaintTracking tr).hasFlow(source, sink)
+}
+
+query predicate isSink(DataFlow::Node node, string kind) {
+ node = ModelOutput::getASinkNode(kind).getARhs()
+}
+
+query predicate isSource(DataFlow::Node node, string kind) {
+ node = ModelOutput::getASourceNode(kind).getAnImmediateUse()
+}
+
+class SyntaxErrorTest extends ModelInput::SinkModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "testlib;;Member[foo],Member[bar];test-sink", "testlib;;Member[foo] Member[bar];test-sink",
+ "testlib;;Member[foo]. Member[bar];test-sink",
+ "testlib;;Member[foo], Member[bar];test-sink",
+ "testlib;;Member[foo]..Member[bar];test-sink",
+ "testlib;;Member[foo] .Member[bar];test-sink", "testlib;;Member[foo]Member[bar];test-sink",
+ "testlib;;Member[foo;test-sink", "testlib;;Member[foo]];test-sink",
+ "testlib;;Member[foo]].Member[bar];test-sink"
+ ]
+ }
+}
+
+query predicate syntaxErrors(AccessPathSyntax::AccessPath path) { path.hasSyntaxError() }
+
+query predicate warning = ModelOutput::getAWarning/0;
diff --git a/python/ql/test/library-tests/frameworks/data/warnings.expected b/python/ql/test/library-tests/frameworks/data/warnings.expected
new file mode 100644
index 00000000000..5cebb548358
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/data/warnings.expected
@@ -0,0 +1,7 @@
+| CSV type row should have 5 columns but has 2: test;TooFewColumns |
+| CSV type row should have 5 columns but has 8: test;TooManyColumns;;;Member[Foo].Instance;too;many;columns |
+| Invalid argument '0-1' in token 'Argument[0-1]' in access path: Method[foo].Argument[0-1] |
+| Invalid argument '*' in token 'Argument[*]' in access path: Method[foo].Argument[*] |
+| Invalid token 'Argument' is missing its arguments, in access path: Method[foo].Argument |
+| Invalid token 'Member' is missing its arguments, in access path: Method[foo].Member |
+| Invalid token name 'Arg' in access path: Method[foo].Arg[0] |
diff --git a/python/ql/test/library-tests/frameworks/data/warnings.ql b/python/ql/test/library-tests/frameworks/data/warnings.ql
new file mode 100644
index 00000000000..3443233179e
--- /dev/null
+++ b/python/ql/test/library-tests/frameworks/data/warnings.ql
@@ -0,0 +1,25 @@
+import python
+import semmle.python.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
+import semmle.python.frameworks.data.internal.ApiGraphModels as ApiGraphModels
+import semmle.python.frameworks.data.ModelsAsData
+
+private class InvalidTypeModel extends ModelInput::TypeModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "test;TooManyColumns;;;Member[Foo].Instance;too;many;columns", //
+ "test;TooFewColumns", //
+ "test;X;test;Y;Method[foo].Arg[0]", //
+ "test;X;test;Y;Method[foo].Argument[0-1]", //
+ "test;X;test;Y;Method[foo].Argument[*]", //
+ "test;X;test;Y;Method[foo].Argument", //
+ "test;X;test;Y;Method[foo].Member", //
+ ]
+ }
+}
+
+class IsTesting extends ApiGraphModels::TestAllModels {
+ IsTesting() { this = this }
+}
+
+query predicate warning = ModelOutput::getAWarning/0;
diff --git a/ruby/ql/consistency-queries/DataFlowConsistency.ql b/ruby/ql/consistency-queries/DataFlowConsistency.ql
index fdc64a8781c..000bbc57899 100644
--- a/ruby/ql/consistency-queries/DataFlowConsistency.ql
+++ b/ruby/ql/consistency-queries/DataFlowConsistency.ql
@@ -9,5 +9,7 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
n instanceof BlockArgumentNode
or
n instanceof SummaryNode
+ or
+ n instanceof HashSplatArgumentsNode
}
}
diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll
index 6b4e11317e6..8f0673c8d99 100644
--- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll
+++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll
@@ -576,7 +576,7 @@ module API {
use(pred, a) and
use(succ, b) and
resolveConstant(b.asExpr().getExpr()) = resolveConstantWriteAccess(c) and
- c.getSuperclassExpr() = a.asExpr().getExpr() and
+ pragma[only_bind_into](c).getSuperclassExpr() = a.asExpr().getExpr() and
lbl = Label::subclass()
)
or
diff --git a/ruby/ql/lib/codeql/ruby/ast/Call.qll b/ruby/ql/lib/codeql/ruby/ast/Call.qll
index 5339f080564..df9e1fa8403 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Call.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll
@@ -145,6 +145,21 @@ class SetterMethodCall extends MethodCall, TMethodCallSynth {
SetterMethodCall() { this = TMethodCallSynth(_, _, _, true, _) }
final override string getAPrimaryQlClass() { result = "SetterMethodCall" }
+
+ /**
+ * Gets the name of the method being called without the trailing `=`. For example, in the following
+ * two statements the target name is `value`:
+ * ```rb
+ * foo.value=(1)
+ * foo.value = 1
+ * ```
+ */
+ final string getTargetName() {
+ exists(string methodName |
+ methodName = this.getMethodName() and
+ result = methodName.prefix(methodName.length() - 1)
+ )
+ }
}
/**
diff --git a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll
index 3b5ed80ff7f..549a7df9216 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll
@@ -109,7 +109,7 @@ class NamedParameter extends Parameter, TNamedParameter {
final VariableAccess getDefiningAccess() {
result = this.getVariable().getDefiningAccess()
or
- result = this.(SimpleParameterSynthImpl).getDefininingAccess()
+ result = this.(SimpleParameterSynthImpl).getDefiningAccess()
}
override AstNode getAChild(string pred) {
diff --git a/ruby/ql/lib/codeql/ruby/ast/Variable.qll b/ruby/ql/lib/codeql/ruby/ast/Variable.qll
index 9952b70b2d1..714c98fa994 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Variable.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Variable.qll
@@ -116,7 +116,7 @@ class VariableAccess extends Expr instanceof VariableAccessImpl {
predicate isImplicitWrite() {
implicitWriteAccess(toGenerated(this))
or
- this = any(SimpleParameterSynthImpl p).getDefininingAccess()
+ this = any(SimpleParameterSynthImpl p).getDefiningAccess()
or
this = any(HashPattern p).getValue(_)
or
diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll
index 0a0a7ddb708..dc7fb8c7695 100644
--- a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll
@@ -38,7 +38,7 @@ class SimpleParameterRealImpl extends SimpleParameterImpl, TSimpleParameterReal
class SimpleParameterSynthImpl extends SimpleParameterImpl, TSimpleParameterSynth {
SimpleParameterSynthImpl() { this = TSimpleParameterSynth(_, _) }
- LocalVariableAccessSynth getDefininingAccess() { synthChild(this, 0, result) }
+ LocalVariableAccessSynth getDefiningAccess() { synthChild(this, 0, result) }
override LocalVariable getVariableImpl() { result = TLocalVariableSynth(this, _) }
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll
index 7adffd04ae3..e586d09be06 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll
@@ -259,7 +259,8 @@ private module Cached {
exists(any(Call c).getKeywordArgument(name))
or
FlowSummaryImplSpecific::ParsePositions::isParsedKeywordParameterPosition(_, name)
- }
+ } or
+ THashSplatArgumentPosition()
cached
newtype TParameterPosition =
@@ -278,6 +279,7 @@ private module Cached {
or
FlowSummaryImplSpecific::ParsePositions::isParsedKeywordArgumentPosition(_, name)
} or
+ THashSplatParameterPosition() or
TAnyParameterPosition()
}
@@ -476,6 +478,9 @@ class ParameterPosition extends TParameterPosition {
/** Holds if this position represents a keyword parameter named `name`. */
predicate isKeyword(string name) { this = TKeywordParameterPosition(name) }
+ /** Holds if this position represents a hash-splat parameter. */
+ predicate isHashSplat() { this = THashSplatParameterPosition() }
+
/**
* Holds if this position represents any parameter. This includes both positional
* and named parameters.
@@ -494,6 +499,8 @@ class ParameterPosition extends TParameterPosition {
or
exists(string name | this.isKeyword(name) and result = "keyword " + name)
or
+ this.isHashSplat() and result = "**"
+ or
this.isAny() and result = "any"
}
}
@@ -512,6 +519,12 @@ class ArgumentPosition extends TArgumentPosition {
/** Holds if this position represents a keyword argument named `name`. */
predicate isKeyword(string name) { this = TKeywordArgumentPosition(name) }
+ /**
+ * Holds if this position represents a synthesized argument containing all keyword
+ * arguments wrapped in a hash.
+ */
+ predicate isHashSplat() { this = THashSplatArgumentPosition() }
+
/** Gets a textual representation of this position. */
string toString() {
this.isSelf() and result = "self"
@@ -521,6 +534,8 @@ class ArgumentPosition extends TArgumentPosition {
exists(int pos | this.isPositional(pos) and result = "position " + pos)
or
exists(string name | this.isKeyword(name) and result = "keyword " + name)
+ or
+ this.isHashSplat() and result = "**"
}
}
@@ -539,5 +554,7 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
or
exists(string name | ppos.isKeyword(name) and apos.isKeyword(name))
or
+ ppos.isHashSplat() and apos.isHashSplat()
+ or
ppos.isAny() and exists(apos)
}
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
index 00068f46735..a6c73b1d893 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
@@ -7,6 +7,7 @@ private import DataFlowDispatch
private import SsaImpl as SsaImpl
private import FlowSummaryImpl as FlowSummaryImpl
private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
+private import codeql.ruby.frameworks.data.ModelsAsData
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(NodeImpl n) { result = n.getEnclosingCallable() }
@@ -179,6 +180,7 @@ private class Argument extends CfgNodes::ExprCfgNode {
this = call.getArgument(i) and
not this.getExpr() instanceof BlockArgument and
not this.getExpr().(Pair).getKey().getConstantValue().isSymbol(_) and
+ not this.getExpr() instanceof HashSplatExpr and
arg.isPositional(i)
)
or
@@ -189,6 +191,10 @@ private class Argument extends CfgNodes::ExprCfgNode {
)
or
this = call.getReceiver() and arg.isSelf()
+ or
+ this = call.getAnArgument() and
+ this.getExpr() instanceof HashSplatExpr and
+ arg.isHashSplat()
}
/** Holds if this expression is the `i`th argument of `c`. */
@@ -216,7 +222,8 @@ private module Cached {
TNormalParameterNode(Parameter p) {
p instanceof SimpleParameter or
p instanceof OptionalParameter or
- p instanceof KeywordParameter
+ p instanceof KeywordParameter or
+ p instanceof HashSplatParameter
} or
TSelfParameterNode(MethodBase m) or
TBlockParameterNode(MethodBase m) or
@@ -232,6 +239,9 @@ private module Cached {
} or
TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
+ } or
+ THashSplatArgumentsNode(CfgNodes::ExprNodes::CallCfgNode c) {
+ exists(Argument arg | arg.isArgumentOf(c, any(ArgumentPosition pos | pos.isKeyword(_))))
}
class TParameterNode =
@@ -349,7 +359,22 @@ private module Cached {
TUnknownElementContent() or
TKnownPairValueContent(ConstantValue cv) or
TUnknownPairValueContent() or
- TFieldContent(string name) { name = any(InstanceVariable v).getName() }
+ TFieldContent(string name) {
+ name = any(InstanceVariable v).getName()
+ or
+ name = "@" + any(SetterMethodCall c).getTargetName()
+ or
+ // The following equation unfortunately leads to a non-monotonic recursion error:
+ // name = any(AccessPathToken a).getAnArgument("Field")
+ // Therefore, we use the following instead to extract the field names from the
+ // external model data. This, unfortunately, does not included any field names used
+ // in models defined in QL code.
+ exists(string input, string output |
+ ModelOutput::relevantSummaryModel(_, _, _, input, output, _)
+ |
+ name = [input, output].regexpFind("(?<=(^|\\.)Field\\[)[^\\]]+(?=\\])", _, _).trim()
+ )
+ }
/**
* Holds if `e` is an `ExprNode` that may be returned by a call to `c`.
@@ -389,6 +414,8 @@ predicate nodeIsHidden(Node n) {
n instanceof SummaryParameterNode
or
n instanceof SynthReturnNode
+ or
+ n instanceof HashSplatArgumentsNode
}
/** An SSA definition, viewed as a node in a data flow graph. */
@@ -473,6 +500,9 @@ private module ParameterNodes {
c.getAParameter() = kp and
pos.isKeyword(kp.getName())
)
+ or
+ parameter = c.getAParameter().(HashSplatParameter) and
+ pos.isHashSplat()
}
override CfgScope getCfgScope() { result = parameter.getCallable() }
@@ -651,6 +681,40 @@ private module ArgumentNodes {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
}
}
+
+ /**
+ * A data-flow node that represents all keyword arguments wrapped in a hash.
+ *
+ * The callee is responsible for filtering out the keyword arguments that are
+ * part of the method signature, such that those cannot end up in the hash-splat
+ * parameter.
+ */
+ class HashSplatArgumentsNode extends ArgumentNode, THashSplatArgumentsNode {
+ CfgNodes::ExprNodes::CallCfgNode c;
+
+ HashSplatArgumentsNode() { this = THashSplatArgumentsNode(c) }
+
+ override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
+ this.sourceArgumentOf(call.asCall(), pos)
+ }
+
+ override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
+ call = c and
+ pos.isHashSplat()
+ }
+ }
+
+ private class HashSplatArgumentsNodeImpl extends NodeImpl, THashSplatArgumentsNode {
+ CfgNodes::ExprNodes::CallCfgNode c;
+
+ HashSplatArgumentsNodeImpl() { this = THashSplatArgumentsNode(c) }
+
+ override CfgScope getCfgScope() { result = c.getExpr().getCfgScope() }
+
+ override Location getLocationImpl() { result = c.getLocation() }
+
+ override string toStringImpl() { result = "**" }
+ }
}
import ArgumentNodes
@@ -807,6 +871,13 @@ predicate jumpStep(Node pred, Node succ) {
succ.asExpr().getExpr().(ConstantReadAccess).getValue() = pred.asExpr().getExpr()
}
+private ContentSet getKeywordContent(string name) {
+ exists(ConstantValue::ConstantSymbolValue key |
+ result.isSingleton(TKnownElementContent(key)) and
+ key.isSymbol(name)
+ )
+}
+
/**
* Holds if data can flow from `node1` to `node2` via an assignment to
* content `c`.
@@ -825,6 +896,16 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
)
).getReceiver()
or
+ // Attribute assignment, `receiver.property = value`
+ node2.(PostUpdateNode).getPreUpdateNode().asExpr() =
+ any(CfgNodes::ExprNodes::MethodCallCfgNode call |
+ node1.asExpr() = call.getArgument(0) and
+ call.getNumberOfArguments() = 1 and
+ c.isSingleton(any(Content::FieldContent ct |
+ ct.getName() = "@" + call.getExpr().(SetterMethodCall).getTargetName()
+ ))
+ ).getReceiver()
+ or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
or
// Needed for pairs passed into method calls where the key is not a symbol,
@@ -845,6 +926,14 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
c.isSingleton(TUnknownPairValueContent())
)
)
+ or
+ // Wrap all keyword arguments in a synthesized hash-splat argument node
+ exists(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition keywordPos, string name |
+ node2 = THashSplatArgumentsNode(call) and
+ node1.asExpr().(Argument).isArgumentOf(call, keywordPos) and
+ keywordPos.isKeyword(name) and
+ c = getKeywordContent(name)
+ )
}
/**
@@ -860,6 +949,19 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
))
)
or
+ // Attribute read, `receiver.field`. Note that we do not check whether
+ // the `field` method is really an attribute reader. This is probably fine
+ // because the read step has only effect if there exists a matching store step
+ // (instance variable assignment or setter method call).
+ node2.asExpr() =
+ any(CfgNodes::ExprNodes::MethodCallCfgNode call |
+ node1.asExpr() = call.getReceiver() and
+ call.getNumberOfArguments() = 0 and
+ c.isSingleton(any(Content::FieldContent ct |
+ ct.getName() = "@" + call.getExpr().getMethodName()
+ ))
+ )
+ or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
}
@@ -870,6 +972,19 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
*/
predicate clearsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
+ or
+ // Filter out keyword arguments that are part of the method signature from
+ // the hash-splat parameter
+ exists(
+ DataFlowCallable callable, ParameterPosition hashSplatPos, ParameterNodeImpl keywordParam,
+ ParameterPosition keywordPos, string name
+ |
+ n.(ParameterNodes::NormalParameterNode).isParameterOf(callable, hashSplatPos) and
+ hashSplatPos.isHashSplat() and
+ keywordParam.isParameterOf(callable, keywordPos) and
+ keywordPos.isKeyword(name) and
+ c = getKeywordContent(name)
+ )
}
/**
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll
index 949f63fe1e9..4b1d3d8f5db 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll
@@ -94,10 +94,16 @@ SummaryComponent interpretComponentSpecific(AccessPathToken c) {
ppos.isAny()
or
ppos.isPositionalLowerBound(AccessPath::parseLowerBound(arg))
+ or
+ arg = "hash-splat" and
+ ppos.isHashSplat()
)
or
result = interpretElementArg(c.getAnArgument("Element"))
or
+ result =
+ FlowSummary::SummaryComponent::content(TSingletonContent(TFieldContent(c.getAnArgument("Field"))))
+ or
exists(ContentSet cs |
FlowSummary::SummaryComponent::content(cs) = interpretElementArg(c.getAnArgument("WithElement")) and
result = FlowSummary::SummaryComponent::withContent(cs)
diff --git a/ruby/ql/lib/codeql/ruby/experimental/Rbi.qll b/ruby/ql/lib/codeql/ruby/experimental/Rbi.qll
new file mode 100644
index 00000000000..d4e620db343
--- /dev/null
+++ b/ruby/ql/lib/codeql/ruby/experimental/Rbi.qll
@@ -0,0 +1,432 @@
+/**
+ * Provides classes and predicates for working with Ruby Interface (RBI) files
+ * and concepts. RBI files are valid Ruby files that can contain type
+ * information used by Sorbet for typechecking.
+ */
+
+private import codeql.ruby.ApiGraphs
+private import codeql.ruby.AST
+private import codeql.ruby.CFG
+private import codeql.ruby.controlflow.CfgNodes
+
+/**
+ * Provides classes and predicates for working with Ruby Interface (RBI) files
+ * and concepts. RBI files are valid Ruby files that can contain type
+ * information used by Sorbet for typechecking.
+ */
+module Rbi {
+ /**
+ * Contains classes representing RBI types.
+ */
+ private module RbiTypes {
+ /**
+ * A node representing a Ruby Interface (RBI) type.
+ */
+ abstract class RbiType extends Expr { }
+
+ /**
+ * A `ConstantReadAccess` as an RBI type. This is typically a reference to a
+ * class or a constant representing a type alias - for example, the read
+ * accesses to `MyList1`, `Integer` and `MyList2` in:
+ * ```rb
+ * class MyList1; end
+ * MyList2 = T.type_alias(MyList1)
+ * sig { params(l: MyList2).returns(Integer) }
+ * def len(l); end
+ * ```
+ */
+ class ConstantReadAccessAsRbiType extends RbiType, ConstantReadAccess { }
+
+ /** A method call where the receiver is `T`. */
+ private class MethodCallAgainstT extends MethodCall {
+ MethodCallAgainstT() { this.getReceiver().(ConstantReadAccess).getName() = "T" }
+ }
+
+ /**
+ * A call to `T.any` - a method that takes `RbiType` parameters, and returns
+ * a type representing the union of those types.
+ */
+ class RbiUnionType extends RbiType, MethodCallAgainstT {
+ RbiUnionType() { this.getMethodName() = "any" }
+
+ /**
+ * Gets a constituent type of this type union.
+ */
+ RbiType getAType() { result = this.getArgument(_) }
+ }
+
+ /**
+ * A call to `T.untyped`.
+ */
+ class RbiUntypedType extends RbiType, MethodCallAgainstT {
+ RbiUntypedType() { this.getMethodName() = "untyped" }
+ }
+
+ /**
+ * A call to `T.nilable`, creating a nilable version of the type provided as
+ * an argument.
+ */
+ class RbiNilableType extends RbiType, MethodCallAgainstT {
+ RbiNilableType() { this.getMethodName() = "nilable" }
+
+ /** Gets the type that this may represent if not nil. */
+ RbiType getUnderlyingType() { result = this.getArgument(0) }
+ }
+
+ /**
+ * A call to `T.type_alias`. The return value of this call can be assigned to
+ * create a type alias.
+ */
+ class RbiTypeAlias extends RbiType, MethodCallAgainstT {
+ RbiTypeAlias() { this.getMethodName() = "type_alias" }
+
+ /**
+ * Gets the type aliased by this call.
+ */
+ RbiType getAliasedType() {
+ exists(ExprNodes::MethodCallCfgNode n | n.getExpr() = this |
+ result = n.getBlock().(ExprNodes::StmtSequenceCfgNode).getLastStmt().getExpr()
+ )
+ }
+ }
+
+ /**
+ * A call to `T.self_type`.
+ */
+ class RbiSelfType extends RbiType, MethodCallAgainstT {
+ RbiSelfType() { this.getMethodName() = "self_type" }
+ }
+
+ /**
+ * A call to `T.noreturn`.
+ */
+ class RbiNoreturnType extends RbiType, MethodCallAgainstT {
+ RbiNoreturnType() { this.getMethodName() = "noreturn" }
+ }
+
+ /**
+ * A `ConstantReadAccess` where the constant is from the `T` module.
+ */
+ private class ConstantReadAccessFromT extends ConstantReadAccess {
+ ConstantReadAccessFromT() { this.getScopeExpr().(ConstantReadAccess).getName() = "T" }
+ }
+
+ /**
+ * A use of `T::Boolean`.
+ */
+ class RbiBooleanType extends RbiType, ConstantReadAccessFromT {
+ RbiBooleanType() { this.getName() = "Boolean" }
+ }
+
+ /**
+ * A use of `T::Array`.
+ */
+ class RbiArrayType extends RbiType, ConstantReadAccessFromT {
+ RbiArrayType() { this.getName() = "Array" }
+
+ /** Gets the type of elements of this array. */
+ RbiType getElementType() {
+ exists(ElementReference refNode | refNode.getReceiver() = this |
+ result = refNode.getArgument(0)
+ )
+ }
+ }
+
+ class RbiHashType extends RbiType, ConstantReadAccessFromT {
+ RbiHashType() { this.getName() = "Hash" }
+
+ private ElementReference getRefNode() { result.getReceiver() = this }
+
+ /** Gets the type of keys of this hash type. */
+ Expr getKeyType() { result = this.getRefNode().getArgument(0) }
+
+ /** Gets the type of values of this hash type. */
+ Expr getValueType() { result = this.getRefNode().getArgument(1) }
+ }
+
+ /**
+ * A call to `T.proc`. This defines a type signature for a proc or block
+ */
+ class ProcCall extends RbiType, SignatureCall, MethodCallAgainstT {
+ ProcCall() { this.getMethodName() = "proc" }
+
+ private ProcReturnsTypeCall getReturnsTypeCall() { result.getProcCall() = this }
+
+ private ProcParamsCall getParamsCall() { result.getProcCall() = this }
+
+ /**
+ * Gets the return type of this type signature.
+ */
+ override ReturnType getReturnType() { result = this.getReturnsTypeCall().getReturnType() }
+
+ /**
+ * Gets the type of a parameter of this type signature.
+ */
+ override ParameterType getAParameterType() {
+ result = this.getParamsCall().getAParameterType()
+ }
+ // TODO: get associated method to which this can be passed
+ }
+ }
+
+ import RbiTypes
+
+ /**
+ * A Ruby Interface (RBI) File. These are valid Ruby files that can contain
+ * type information used by Sorbet for typechecking.
+ *
+ * RBI files can contain project source code, or act as external type
+ * definition files for existing Ruby code, which may include code in gems.
+ */
+ class RbiFile extends File {
+ RbiFile() { this.getExtension() = "rbi" }
+ }
+
+ private newtype TReturnType =
+ TRbiType(RbiType t) { exists(ReturnsCall r | r.getRbiType() = t) } or
+ TVoidType()
+
+ /** A return type of a method. */
+ class ReturnType extends TReturnType {
+ /** Gets a textual representation of this node. */
+ cached
+ string toString() {
+ result = this.getRbiType().toString()
+ or
+ this.isVoidType() and result = "(void)"
+ }
+
+ /** Gets the underlying RbiType, if any. */
+ RbiType getRbiType() { exists(RbiType t | this = TRbiType(t) | result = t) }
+
+ /** Holds if this is the void type. */
+ predicate isVoidType() { this = TVoidType() }
+ }
+
+ /**
+ * A call that defines a type signature for a method or proc.
+ */
+ abstract class SignatureCall extends MethodCall {
+ /**
+ * Gets the return type of this type signature.
+ */
+ abstract ReturnType getReturnType();
+
+ /**
+ * Gets the type of a parameter of this type signature.
+ */
+ abstract ParameterType getAParameterType();
+ }
+
+ private predicate isMethodSignatureCallNode(CfgNode n) {
+ n.(ExprCfgNode).getExpr() instanceof MethodSignatureCall
+ }
+
+ /**
+ * Holds if `n` is the `i`th transitive successor node of `sigNode` where there
+ * are no intervening nodes corresponding to `MethodSignatureCall`s.
+ */
+ private predicate methodSignatureSuccessorNodeRanked(CfgNode sigNode, CfgNode n, int i) {
+ // direct successor
+ i = 1 and
+ n = sigNode.getASuccessor() and
+ not isMethodSignatureCallNode(n)
+ or
+ // transitive successor
+ i > 1 and
+ exists(CfgNode np | n = np.getASuccessor() |
+ methodSignatureSuccessorNodeRanked(sigNode, np, i - 1) and
+ not isMethodSignatureCallNode(np)
+ )
+ }
+
+ /** A call to `sig` to define the type signature of a method. */
+ class MethodSignatureCall extends SignatureCall {
+ MethodSignatureCall() { this.getMethodName() = "sig" }
+
+ private MethodReturnsTypeCall getReturnsTypeCall() { result.getMethodSignatureCall() = this }
+
+ private MethodParamsCall getParamsCall() { result.getMethodSignatureCall() = this }
+
+ private ExprCfgNode getCfgNode() { result.getExpr() = this }
+
+ /**
+ * Gets the method whose type signature is defined by this call.
+ */
+ MethodBase getAssociatedMethod() {
+ result =
+ min(ExprCfgNode methodCfgNode, int i |
+ methodSignatureSuccessorNodeRanked(this.getCfgNode(), methodCfgNode, i) and
+ methodCfgNode.getExpr() instanceof MethodBase
+ |
+ methodCfgNode order by i
+ ).getExpr()
+ }
+
+ /**
+ * Gets a call to `attr_reader` or `attr_accessor` where the return type of
+ * the generated method is described by this call.
+ */
+ MethodCall getAssociatedAttrReaderCall() {
+ result =
+ min(ExprNodes::MethodCallCfgNode c, int i |
+ c.getExpr().getMethodName() = ["attr_reader", "attr_accessor"] and
+ methodSignatureSuccessorNodeRanked(this.getCfgNode(), c, i)
+ |
+ c order by i
+ ).getExpr()
+ }
+
+ /**
+ * Gets the return type of this type signature.
+ */
+ override ReturnType getReturnType() { result = this.getReturnsTypeCall().getReturnType() }
+
+ /**
+ * Gets the type of a parameter of this type signature.
+ */
+ override ParameterType getAParameterType() { result = this.getParamsCall().getAParameterType() }
+ }
+
+ /**
+ * A method call that defines either:
+ * - the parameters to, or
+ * - the return type of
+ * a method.
+ */
+ class MethodSignatureDefiningCall extends MethodCall {
+ private MethodSignatureCall sigCall;
+
+ MethodSignatureDefiningCall() {
+ exists(MethodCall c | c = sigCall.getBlock().getAChild() |
+ // The typical pattern for the contents of a `sig` block is something
+ // like `params().returns()` - we want to
+ // pick up both of these calls.
+ this = c.getReceiver*()
+ )
+ }
+
+ /**
+ * Gets the enclosing `sig` call that defines the overall type signature
+ * for the method associated with this call.
+ */
+ MethodSignatureCall getMethodSignatureCall() { result = sigCall }
+ }
+
+ /**
+ * A call to `params`. This defines the types of parameters to a method or proc.
+ */
+ class ParamsCall extends MethodCall {
+ ParamsCall() { this.getMethodName() = "params" }
+
+ /**
+ * Gets the type of a parameter defined by this call.
+ */
+ ParameterType getAParameterType() { result = this.getArgument(_) }
+ }
+
+ abstract class ReturnsTypeCall extends MethodCall {
+ abstract ReturnType getReturnType();
+ }
+
+ /**
+ * A call to `returns`. Defines the return type of a method or proc.
+ */
+ class ReturnsCall extends MethodCall {
+ ReturnsCall() { this.getMethodName() = "returns" }
+
+ /**
+ * Gets the `RbiType` return type of this call.
+ */
+ RbiType getRbiType() { result = this.getArgument(0) }
+
+ /**
+ * Gets the wrapped `ReturnType` of this call.
+ */
+ ReturnType getReturnType() { result.getRbiType() = this.getRbiType() }
+ }
+
+ /**
+ * A call to `void`. Essentially a "don't-care" for the return type of a method or proc.
+ */
+ class VoidCall extends MethodCall {
+ VoidCall() { this.getMethodName() = "void" }
+
+ /**
+ * Gets the wrapped `ReturnType` of this call.
+ */
+ ReturnType getReturnType() { result.isVoidType() }
+ }
+
+ /** A call that defines the return type of a method. */
+ abstract class MethodReturnsTypeCall extends ReturnsTypeCall, MethodSignatureDefiningCall { }
+
+ /** A call to `params` that defines the parameter types of a method */
+ class MethodParamsCall extends ParamsCall, MethodSignatureDefiningCall { }
+
+ /** A call to `returns` that defines the return type of a method. */
+ class MethodReturnsCall extends MethodReturnsTypeCall instanceof ReturnsCall {
+ override ReturnType getReturnType() { result = ReturnsCall.super.getReturnType() }
+ }
+
+ /** A call to `void` that spcifies that a given method does not return a useful value. */
+ class MethodVoidCall extends MethodReturnsTypeCall instanceof VoidCall {
+ override ReturnType getReturnType() { result = VoidCall.super.getReturnType() }
+ }
+
+ /** A call that defines part of the type signature of a proc or block argument. */
+ class ProcSignatureDefiningCall extends MethodCall, RbiType {
+ private ProcCall procCall;
+
+ ProcSignatureDefiningCall() { this.getReceiver+() = procCall }
+
+ /**
+ * Gets the `proc` call that defines the complete type signature for the
+ * associated proc or block argument.
+ */
+ ProcCall getProcCall() { result = procCall }
+ }
+
+ /** A call that defines the return type of a proc or block */
+ abstract class ProcReturnsTypeCall extends ReturnsTypeCall, ProcSignatureDefiningCall { }
+
+ /** A call that defines the parameter types of a proc or block. */
+ class ProcParamsCall extends ParamsCall, ProcSignatureDefiningCall { }
+
+ /** A call that defines the return type of a non-void proc or block. */
+ class ProcReturnsCall extends ProcReturnsTypeCall instanceof ReturnsCall {
+ override ReturnType getReturnType() { result = ReturnsCall.super.getReturnType() }
+ }
+
+ /**
+ * A call to `void` that spcifies that a given proc or block does not return
+ * a useful value.
+ */
+ class ProcVoidCall extends ProcReturnsTypeCall instanceof VoidCall {
+ override ReturnType getReturnType() { result = VoidCall.super.getReturnType() }
+ }
+
+ /**
+ * A pair defining the type of a parameter to a method.
+ */
+ class ParameterType extends Pair {
+ private RbiType t;
+
+ ParameterType() { t = this.getValue() }
+
+ /** Gets the `RbiType` of this parameter. */
+ RbiType getType() { result = t }
+
+ private SignatureCall getOuterMethodSignatureCall() { this = result.getAParameterType() }
+
+ private MethodBase getAssociatedMethod() {
+ result = this.getOuterMethodSignatureCall().(MethodSignatureCall).getAssociatedMethod()
+ }
+
+ /** Gets the parameter to which this type applies. */
+ NamedParameter getParameter() {
+ result = this.getAssociatedMethod().getAParameter() and
+ result.getName() = this.getKey().getConstantValue().getStringlikeValue()
+ }
+ }
+}
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll
index 6f0d43fb2aa..f9e97276681 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll
@@ -275,7 +275,18 @@ private class ActiveRecordModelFinderCall extends ActiveRecordModelInstantiation
exists(MethodCall call, Expr recv |
call = this.asExpr().getExpr() and
recv = getUltimateReceiver(call) and
- resolveConstant(recv) = cls.getAQualifiedName() and
+ (
+ // The receiver refers to an `ActiveRecordModelClass` by name
+ resolveConstant(recv) = cls.getAQualifiedName()
+ or
+ // The receiver is self, and the call is within a singleton method of
+ // the `ActiveRecordModelClass`
+ recv instanceof SelfVariableAccess and
+ exists(SingletonMethod callScope |
+ callScope = call.getCfgScope() and
+ callScope = cls.getAMethod()
+ )
+ ) and
call.getMethodName() = finderMethodName()
)
}
@@ -293,18 +304,24 @@ private class ActiveRecordModelClassSelfReference extends ActiveRecordModelInsta
m = this.getCfgScope() and
m.getEnclosingModule() = cls and
m = cls.getAMethod()
- )
+ ) and
+ // In a singleton method, `self` refers to the class itself rather than an
+ // instance of that class
+ not this.getSelfScope() instanceof SingletonMethod
}
final override ActiveRecordModelClass getClass() { result = cls }
}
-// A (locally tracked) active record model object
-private class ActiveRecordInstance extends DataFlow::Node {
+/**
+ * An instance of an `ActiveRecord` model object.
+ */
+class ActiveRecordInstance extends DataFlow::Node {
private ActiveRecordModelInstantiation instantiation;
ActiveRecordInstance() { this = instantiation or instantiation.flowsTo(this) }
+ /** Gets the `ActiveRecordModelClass` that this is an instance of. */
ActiveRecordModelClass getClass() { result = instantiation.getClass() }
}
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Core.qll b/ruby/ql/lib/codeql/ruby/frameworks/Core.qll
index 54c8207b7a4..1ef6d8d65e5 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/Core.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/Core.qll
@@ -73,3 +73,15 @@ private class SplatSummary extends SummarizedCallable {
preservesValue = true
}
}
+
+private class HashSplatSummary extends SummarizedCallable {
+ HashSplatSummary() { this = "**(hash-splat)" }
+
+ override HashSplatExpr getACall() { any() }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ input = "Argument[self].WithElement[any]" and
+ output = "ReturnValue" and
+ preservesValue = true
+ }
+}
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll
index 0d4be60e9fb..2cce0b78957 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/core/Hash.qll
@@ -65,6 +65,22 @@ module Hash {
}
}
+ private class HashLiteralHashSplatSummary extends SummarizedCallable {
+ HashLiteralHashSplatSummary() { this = "Hash.[**]" }
+
+ final override MethodCall getACall() {
+ result = API::getTopLevelMember("Hash").getAMethodCall("[]").getExprNode().getExpr() and
+ result.getAnArgument() instanceof HashSplatExpr
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ // { **hash }
+ input = "Argument[hash-splat].WithElement[any]" and
+ output = "ReturnValue" and
+ preservesValue = true
+ }
+ }
+
/**
* `Hash[]` called on an existing hash, e.g.
*
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll
index 127d9ca5122..69563a3eab4 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll
@@ -299,7 +299,7 @@ private class AccessPathRange extends AccessPath::Range {
bindingset[token]
API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
// API graphs use the same label for arguments and parameters. An edge originating from a
- // use-node represents be an argument, and an edge originating from a def-node represents a parameter.
+ // use-node represents an argument, and an edge originating from a def-node represents a parameter.
// We just map both to the same thing.
token.getName() = ["Argument", "Parameter"] and
result = node.getParameter(AccessPath::parseIntUnbounded(token.getAnArgument()))
diff --git a/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.qhelp b/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.qhelp
index 4b1c31cb5d7..70fb90666f1 100644
--- a/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.qhelp
+++ b/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.qhelp
@@ -44,7 +44,7 @@ replace further instances of the string that result from earlier replacements.
For example, consider the code snippet s.gsub /\/\.\.\//, "", which attempts to strip
-out all occurences of /../ from s. This will not work as expected: for the
+out all occurrences of /../ from s. This will not work as expected: for the
string /./.././, for example, it will remove the single occurrence of /../
in the middle, but the remainder of the string then becomes /../, which is another
instance of the substring we were trying to remove.
diff --git a/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.ql b/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.ql
index 0c80e8847c9..f6090387261 100644
--- a/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.ql
+++ b/ruby/ql/src/queries/security/cwe-116/IncompleteSanitization.ql
@@ -116,7 +116,7 @@ predicate allBackslashesEscaped(DataFlow::Node node) {
* Holds if `sub` looks like a string substitution call that deliberately
* removes the first occurrence of `str`.
*/
-predicate removesFirstOccurence(StringSubstitutionCall sub, string str) {
+predicate removesFirstOccurrence(StringSubstitutionCall sub, string str) {
not sub.isGlobal() and sub.replaces(str, "")
}
@@ -158,8 +158,8 @@ predicate isDelimiterUnwrapper(StringSubstitutionCall leftUnwrap, StringSubstitu
or
left = "'" and right = "'"
|
- removesFirstOccurence(leftUnwrap, left) and
- removesFirstOccurence(rightUnwrap, right) and
+ removesFirstOccurrence(leftUnwrap, left) and
+ removesFirstOccurrence(rightUnwrap, right) and
rightUnwrap = getAMethodCall(leftUnwrap)
)
}
diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected
index 7975d3d5eb1..9ee03271537 100644
--- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected
+++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected
@@ -33,6 +33,34 @@ edges
| instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:20:1:20:3 | [post] bar [@field] : |
| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : |
| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field |
+| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | instance_variables.rb:25:6:25:9 | foo1 [@field] : |
+| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | instance_variables.rb:25:6:25:9 | foo1 [@field] : |
+| instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : |
+| instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : |
+| instance_variables.rb:25:6:25:9 | foo1 [@field] : | instance_variables.rb:25:6:25:15 | call to field |
+| instance_variables.rb:25:6:25:9 | foo1 [@field] : | instance_variables.rb:25:6:25:15 | call to field |
+| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | instance_variables.rb:29:6:29:9 | foo2 [@field] : |
+| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | instance_variables.rb:29:6:29:9 | foo2 [@field] : |
+| instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : |
+| instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:29:6:29:19 | call to get_field |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:29:6:29:19 | call to get_field |
+| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | instance_variables.rb:33:6:33:9 | foo3 [@field] : |
+| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | instance_variables.rb:33:6:33:9 | foo3 [@field] : |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : |
+| instance_variables.rb:33:6:33:9 | foo3 [@field] : | instance_variables.rb:33:6:33:15 | call to field |
+| instance_variables.rb:33:6:33:9 | foo3 [@field] : | instance_variables.rb:33:6:33:15 | call to field |
+| instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : | instance_variables.rb:37:6:37:9 | foo4 [@other] : |
+| instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : | instance_variables.rb:37:6:37:9 | foo4 [@other] : |
+| instance_variables.rb:36:14:36:23 | call to source : | instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : |
+| instance_variables.rb:36:14:36:23 | call to source : | instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : |
+| instance_variables.rb:37:6:37:9 | foo4 [@other] : | instance_variables.rb:37:6:37:15 | call to other |
+| instance_variables.rb:37:6:37:9 | foo4 [@other] : | instance_variables.rb:37:6:37:15 | call to other |
nodes
| instance_variables.rb:2:19:2:19 | x : | semmle.label | x : |
| instance_variables.rb:2:19:2:19 | x : | semmle.label | x : |
@@ -70,6 +98,38 @@ nodes
| instance_variables.rb:20:15:20:23 | call to source : | semmle.label | call to source : |
| instance_variables.rb:21:6:21:8 | bar [@field] : | semmle.label | bar [@field] : |
| instance_variables.rb:21:6:21:18 | call to inc_field | semmle.label | call to inc_field |
+| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : |
+| instance_variables.rb:24:1:24:4 | [post] foo1 [@field] : | semmle.label | [post] foo1 [@field] : |
+| instance_variables.rb:24:14:24:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:24:14:24:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:25:6:25:9 | foo1 [@field] : | semmle.label | foo1 [@field] : |
+| instance_variables.rb:25:6:25:9 | foo1 [@field] : | semmle.label | foo1 [@field] : |
+| instance_variables.rb:25:6:25:15 | call to field | semmle.label | call to field |
+| instance_variables.rb:25:6:25:15 | call to field | semmle.label | call to field |
+| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : |
+| instance_variables.rb:28:1:28:4 | [post] foo2 [@field] : | semmle.label | [post] foo2 [@field] : |
+| instance_variables.rb:28:14:28:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:28:14:28:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | semmle.label | foo2 [@field] : |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | semmle.label | foo2 [@field] : |
+| instance_variables.rb:29:6:29:19 | call to get_field | semmle.label | call to get_field |
+| instance_variables.rb:29:6:29:19 | call to get_field | semmle.label | call to get_field |
+| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : |
+| instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : | semmle.label | [post] foo3 [@field] : |
+| instance_variables.rb:32:16:32:25 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:32:16:32:25 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:33:6:33:9 | foo3 [@field] : | semmle.label | foo3 [@field] : |
+| instance_variables.rb:33:6:33:9 | foo3 [@field] : | semmle.label | foo3 [@field] : |
+| instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field |
+| instance_variables.rb:33:6:33:15 | call to field | semmle.label | call to field |
+| instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : | semmle.label | [post] foo4 [@other] : |
+| instance_variables.rb:36:1:36:4 | [post] foo4 [@other] : | semmle.label | [post] foo4 [@other] : |
+| instance_variables.rb:36:14:36:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:36:14:36:23 | call to source : | semmle.label | call to source : |
+| instance_variables.rb:37:6:37:9 | foo4 [@other] : | semmle.label | foo4 [@other] : |
+| instance_variables.rb:37:6:37:9 | foo4 [@other] : | semmle.label | foo4 [@other] : |
+| instance_variables.rb:37:6:37:15 | call to other | semmle.label | call to other |
+| instance_variables.rb:37:6:37:15 | call to other | semmle.label | call to other |
subpaths
| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : |
| instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:16:1:16:3 | [post] foo [@field] : |
@@ -78,7 +138,15 @@ subpaths
| instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:20:1:20:3 | [post] bar [@field] : |
| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field |
| instance_variables.rb:21:6:21:8 | bar [@field] : | instance_variables.rb:8:5:10:7 | self in inc_field [@field] : | instance_variables.rb:9:9:9:14 | [post] self [@field] : | instance_variables.rb:21:6:21:18 | call to inc_field |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:29:6:29:19 | call to get_field |
+| instance_variables.rb:29:6:29:9 | foo2 [@field] : | instance_variables.rb:5:5:7:7 | self in get_field [@field] : | instance_variables.rb:6:9:6:21 | return : | instance_variables.rb:29:6:29:19 | call to get_field |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : |
+| instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:2:19:2:19 | x : | instance_variables.rb:3:9:3:14 | [post] self [@field] : | instance_variables.rb:32:1:32:4 | [post] foo3 [@field] : |
#select
| instance_variables.rb:12:10:12:13 | @foo | instance_variables.rb:11:12:11:22 | call to source : | instance_variables.rb:12:10:12:13 | @foo | $@ | instance_variables.rb:11:12:11:22 | call to source : | call to source : |
| instance_variables.rb:17:6:17:18 | call to get_field | instance_variables.rb:16:15:16:24 | call to source : | instance_variables.rb:17:6:17:18 | call to get_field | $@ | instance_variables.rb:16:15:16:24 | call to source : | call to source : |
| instance_variables.rb:21:6:21:18 | call to inc_field | instance_variables.rb:20:15:20:23 | call to source : | instance_variables.rb:21:6:21:18 | call to inc_field | $@ | instance_variables.rb:20:15:20:23 | call to source : | call to source : |
+| instance_variables.rb:25:6:25:15 | call to field | instance_variables.rb:24:14:24:23 | call to source : | instance_variables.rb:25:6:25:15 | call to field | $@ | instance_variables.rb:24:14:24:23 | call to source : | call to source : |
+| instance_variables.rb:29:6:29:19 | call to get_field | instance_variables.rb:28:14:28:23 | call to source : | instance_variables.rb:29:6:29:19 | call to get_field | $@ | instance_variables.rb:28:14:28:23 | call to source : | call to source : |
+| instance_variables.rb:33:6:33:15 | call to field | instance_variables.rb:32:16:32:25 | call to source : | instance_variables.rb:33:6:33:15 | call to field | $@ | instance_variables.rb:32:16:32:25 | call to source : | call to source : |
+| instance_variables.rb:37:6:37:15 | call to other | instance_variables.rb:36:14:36:23 | call to source : | instance_variables.rb:37:6:37:15 | call to other | $@ | instance_variables.rb:36:14:36:23 | call to source : | call to source : |
diff --git a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb
index be91c6da8fb..93bdf207be2 100644
--- a/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb
+++ b/ruby/ql/test/library-tests/dataflow/global/instance_variables.rb
@@ -18,4 +18,20 @@ sink(foo.get_field) # $ hasValueFlow=42
bar = Foo.new
bar.set_field(source(5))
-sink(bar.inc_field) # $ hasTaintFlow=5
\ No newline at end of file
+sink(bar.inc_field) # $ hasTaintFlow=5
+
+foo1 = Foo.new
+foo1.field = source(20)
+sink(foo1.field) # $ hasValueFlow=20
+
+foo2 = Foo.new
+foo2.field = source(21)
+sink(foo2.get_field) # $ hasValueFlow=21
+
+foo3 = Foo.new
+foo3.set_field(source(22))
+sink(foo3.field) # $ hasValueFlow=22
+
+foo4 = "hello"
+foo4.other = source(23)
+sink(foo4.other) # $ hasValueFlow=23
diff --git a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
index a573f2cfc99..a3ce961c7a9 100644
--- a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
+++ b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
@@ -508,6 +508,24 @@ edges
| hash_flow.rb:721:9:721:12 | hash [element :c] : | hash_flow.rb:721:9:721:31 | call to fetch_values [element] : |
| hash_flow.rb:721:9:721:31 | call to fetch_values [element] : | hash_flow.rb:722:10:722:10 | b [element] : |
| hash_flow.rb:722:10:722:10 | b [element] : | hash_flow.rb:722:10:722:13 | ...[...] |
+| hash_flow.rb:729:15:729:25 | call to taint : | hash_flow.rb:738:16:738:20 | hash1 [element :a] : |
+| hash_flow.rb:731:15:731:25 | call to taint : | hash_flow.rb:738:16:738:20 | hash1 [element :c] : |
+| hash_flow.rb:734:15:734:25 | call to taint : | hash_flow.rb:738:44:738:48 | hash2 [element :d] : |
+| hash_flow.rb:736:15:736:25 | call to taint : | hash_flow.rb:738:44:738:48 | hash2 [element :f] : |
+| hash_flow.rb:738:14:738:20 | ** ... [element :a] : | hash_flow.rb:739:10:739:13 | hash [element :a] : |
+| hash_flow.rb:738:14:738:20 | ** ... [element :c] : | hash_flow.rb:741:10:741:13 | hash [element :c] : |
+| hash_flow.rb:738:16:738:20 | hash1 [element :a] : | hash_flow.rb:738:14:738:20 | ** ... [element :a] : |
+| hash_flow.rb:738:16:738:20 | hash1 [element :c] : | hash_flow.rb:738:14:738:20 | ** ... [element :c] : |
+| hash_flow.rb:738:29:738:39 | call to taint : | hash_flow.rb:745:10:745:13 | hash [element :g] : |
+| hash_flow.rb:738:42:738:48 | ** ... [element :d] : | hash_flow.rb:742:10:742:13 | hash [element :d] : |
+| hash_flow.rb:738:42:738:48 | ** ... [element :f] : | hash_flow.rb:744:10:744:13 | hash [element :f] : |
+| hash_flow.rb:738:44:738:48 | hash2 [element :d] : | hash_flow.rb:738:42:738:48 | ** ... [element :d] : |
+| hash_flow.rb:738:44:738:48 | hash2 [element :f] : | hash_flow.rb:738:42:738:48 | ** ... [element :f] : |
+| hash_flow.rb:739:10:739:13 | hash [element :a] : | hash_flow.rb:739:10:739:17 | ...[...] |
+| hash_flow.rb:741:10:741:13 | hash [element :c] : | hash_flow.rb:741:10:741:17 | ...[...] |
+| hash_flow.rb:742:10:742:13 | hash [element :d] : | hash_flow.rb:742:10:742:17 | ...[...] |
+| hash_flow.rb:744:10:744:13 | hash [element :f] : | hash_flow.rb:744:10:744:17 | ...[...] |
+| hash_flow.rb:745:10:745:13 | hash [element :g] : | hash_flow.rb:745:10:745:17 | ...[...] |
nodes
| hash_flow.rb:11:15:11:24 | call to taint : | semmle.label | call to taint : |
| hash_flow.rb:13:12:13:21 | call to taint : | semmle.label | call to taint : |
@@ -1062,6 +1080,29 @@ nodes
| hash_flow.rb:721:9:721:31 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : |
| hash_flow.rb:722:10:722:10 | b [element] : | semmle.label | b [element] : |
| hash_flow.rb:722:10:722:13 | ...[...] | semmle.label | ...[...] |
+| hash_flow.rb:729:15:729:25 | call to taint : | semmle.label | call to taint : |
+| hash_flow.rb:731:15:731:25 | call to taint : | semmle.label | call to taint : |
+| hash_flow.rb:734:15:734:25 | call to taint : | semmle.label | call to taint : |
+| hash_flow.rb:736:15:736:25 | call to taint : | semmle.label | call to taint : |
+| hash_flow.rb:738:14:738:20 | ** ... [element :a] : | semmle.label | ** ... [element :a] : |
+| hash_flow.rb:738:14:738:20 | ** ... [element :c] : | semmle.label | ** ... [element :c] : |
+| hash_flow.rb:738:16:738:20 | hash1 [element :a] : | semmle.label | hash1 [element :a] : |
+| hash_flow.rb:738:16:738:20 | hash1 [element :c] : | semmle.label | hash1 [element :c] : |
+| hash_flow.rb:738:29:738:39 | call to taint : | semmle.label | call to taint : |
+| hash_flow.rb:738:42:738:48 | ** ... [element :d] : | semmle.label | ** ... [element :d] : |
+| hash_flow.rb:738:42:738:48 | ** ... [element :f] : | semmle.label | ** ... [element :f] : |
+| hash_flow.rb:738:44:738:48 | hash2 [element :d] : | semmle.label | hash2 [element :d] : |
+| hash_flow.rb:738:44:738:48 | hash2 [element :f] : | semmle.label | hash2 [element :f] : |
+| hash_flow.rb:739:10:739:13 | hash [element :a] : | semmle.label | hash [element :a] : |
+| hash_flow.rb:739:10:739:17 | ...[...] | semmle.label | ...[...] |
+| hash_flow.rb:741:10:741:13 | hash [element :c] : | semmle.label | hash [element :c] : |
+| hash_flow.rb:741:10:741:17 | ...[...] | semmle.label | ...[...] |
+| hash_flow.rb:742:10:742:13 | hash [element :d] : | semmle.label | hash [element :d] : |
+| hash_flow.rb:742:10:742:17 | ...[...] | semmle.label | ...[...] |
+| hash_flow.rb:744:10:744:13 | hash [element :f] : | semmle.label | hash [element :f] : |
+| hash_flow.rb:744:10:744:17 | ...[...] | semmle.label | ...[...] |
+| hash_flow.rb:745:10:745:13 | hash [element :g] : | semmle.label | hash [element :g] : |
+| hash_flow.rb:745:10:745:17 | ...[...] | semmle.label | ...[...] |
subpaths
#select
| hash_flow.rb:22:10:22:17 | ...[...] | hash_flow.rb:11:15:11:24 | call to taint : | hash_flow.rb:22:10:22:17 | ...[...] | $@ | hash_flow.rb:11:15:11:24 | call to taint : | call to taint : |
@@ -1229,3 +1270,8 @@ subpaths
| hash_flow.rb:720:10:720:13 | ...[...] | hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:720:10:720:13 | ...[...] | $@ | hash_flow.rb:715:15:715:25 | call to taint : | call to taint : |
| hash_flow.rb:722:10:722:13 | ...[...] | hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:722:10:722:13 | ...[...] | $@ | hash_flow.rb:715:15:715:25 | call to taint : | call to taint : |
| hash_flow.rb:722:10:722:13 | ...[...] | hash_flow.rb:717:15:717:25 | call to taint : | hash_flow.rb:722:10:722:13 | ...[...] | $@ | hash_flow.rb:717:15:717:25 | call to taint : | call to taint : |
+| hash_flow.rb:739:10:739:17 | ...[...] | hash_flow.rb:729:15:729:25 | call to taint : | hash_flow.rb:739:10:739:17 | ...[...] | $@ | hash_flow.rb:729:15:729:25 | call to taint : | call to taint : |
+| hash_flow.rb:741:10:741:17 | ...[...] | hash_flow.rb:731:15:731:25 | call to taint : | hash_flow.rb:741:10:741:17 | ...[...] | $@ | hash_flow.rb:731:15:731:25 | call to taint : | call to taint : |
+| hash_flow.rb:742:10:742:17 | ...[...] | hash_flow.rb:734:15:734:25 | call to taint : | hash_flow.rb:742:10:742:17 | ...[...] | $@ | hash_flow.rb:734:15:734:25 | call to taint : | call to taint : |
+| hash_flow.rb:744:10:744:17 | ...[...] | hash_flow.rb:736:15:736:25 | call to taint : | hash_flow.rb:744:10:744:17 | ...[...] | $@ | hash_flow.rb:736:15:736:25 | call to taint : | call to taint : |
+| hash_flow.rb:745:10:745:17 | ...[...] | hash_flow.rb:738:29:738:39 | call to taint : | hash_flow.rb:745:10:745:17 | ...[...] | $@ | hash_flow.rb:738:29:738:39 | call to taint : | call to taint : |
diff --git a/ruby/ql/test/library-tests/dataflow/hash-flow/hash_flow.rb b/ruby/ql/test/library-tests/dataflow/hash-flow/hash_flow.rb
index 065cc5d5bd3..f9de83dd47c 100644
--- a/ruby/ql/test/library-tests/dataflow/hash-flow/hash_flow.rb
+++ b/ruby/ql/test/library-tests/dataflow/hash-flow/hash_flow.rb
@@ -723,3 +723,27 @@ def m44(x)
end
m44(:c)
+
+def m45()
+ hash1 = {
+ :a => taint(45.1),
+ :b => 1,
+ :c => taint(45.2)
+ }
+ hash2 = {
+ :d => taint(45.3),
+ :e => 2,
+ :f => taint(45.4)
+ }
+ hash = { **hash1, :g => taint(45.5), **hash2, :h => 3 }
+ sink(hash[:a]) # $ hasValueFlow=45.1
+ sink(hash[:b])
+ sink(hash[:c]) # $ hasValueFlow=45.2
+ sink(hash[:d]) # $ hasValueFlow=45.3
+ sink(hash[:e])
+ sink(hash[:f]) # $ hasValueFlow=45.4
+ sink(hash[:g]) # $ hasValueFlow=45.5
+ sink(hash[:h])
+end
+
+m45()
\ No newline at end of file
diff --git a/ruby/ql/test/library-tests/dataflow/params/params-flow.expected b/ruby/ql/test/library-tests/dataflow/params/params-flow.expected
index 1caa2604b11..3df4f046a07 100644
--- a/ruby/ql/test/library-tests/dataflow/params/params-flow.expected
+++ b/ruby/ql/test/library-tests/dataflow/params/params-flow.expected
@@ -12,6 +12,20 @@ edges
| params_flow.rb:22:27:22:34 | call to taint : | params_flow.rb:16:13:16:14 | p1 : |
| params_flow.rb:23:16:23:23 | call to taint : | params_flow.rb:16:18:16:19 | p2 : |
| params_flow.rb:23:33:23:40 | call to taint : | params_flow.rb:16:13:16:14 | p1 : |
+| params_flow.rb:25:12:25:13 | p1 : | params_flow.rb:26:10:26:11 | p1 |
+| params_flow.rb:25:17:25:24 | **kwargs [element :p2] : | params_flow.rb:28:11:28:16 | kwargs [element :p2] : |
+| params_flow.rb:25:17:25:24 | **kwargs [element :p3] : | params_flow.rb:29:11:29:16 | kwargs [element :p3] : |
+| params_flow.rb:28:11:28:16 | kwargs [element :p2] : | params_flow.rb:28:11:28:21 | ...[...] : |
+| params_flow.rb:28:11:28:21 | ...[...] : | params_flow.rb:28:10:28:22 | ( ... ) |
+| params_flow.rb:29:11:29:16 | kwargs [element :p3] : | params_flow.rb:29:11:29:21 | ...[...] : |
+| params_flow.rb:29:11:29:21 | ...[...] : | params_flow.rb:29:10:29:22 | ( ... ) |
+| params_flow.rb:33:12:33:19 | call to taint : | params_flow.rb:25:12:25:13 | p1 : |
+| params_flow.rb:33:26:33:34 | call to taint : | params_flow.rb:25:17:25:24 | **kwargs [element :p2] : |
+| params_flow.rb:33:41:33:49 | call to taint : | params_flow.rb:25:17:25:24 | **kwargs [element :p3] : |
+| params_flow.rb:34:14:34:22 | call to taint : | params_flow.rb:35:25:35:28 | args [element :p3] : |
+| params_flow.rb:35:12:35:20 | call to taint : | params_flow.rb:25:12:25:13 | p1 : |
+| params_flow.rb:35:23:35:28 | ** ... [element :p3] : | params_flow.rb:25:17:25:24 | **kwargs [element :p3] : |
+| params_flow.rb:35:25:35:28 | args [element :p3] : | params_flow.rb:35:23:35:28 | ** ... [element :p3] : |
nodes
| params_flow.rb:9:16:9:17 | p1 : | semmle.label | p1 : |
| params_flow.rb:9:20:9:21 | p2 : | semmle.label | p2 : |
@@ -29,6 +43,23 @@ nodes
| params_flow.rb:22:27:22:34 | call to taint : | semmle.label | call to taint : |
| params_flow.rb:23:16:23:23 | call to taint : | semmle.label | call to taint : |
| params_flow.rb:23:33:23:40 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:25:12:25:13 | p1 : | semmle.label | p1 : |
+| params_flow.rb:25:17:25:24 | **kwargs [element :p2] : | semmle.label | **kwargs [element :p2] : |
+| params_flow.rb:25:17:25:24 | **kwargs [element :p3] : | semmle.label | **kwargs [element :p3] : |
+| params_flow.rb:26:10:26:11 | p1 | semmle.label | p1 |
+| params_flow.rb:28:10:28:22 | ( ... ) | semmle.label | ( ... ) |
+| params_flow.rb:28:11:28:16 | kwargs [element :p2] : | semmle.label | kwargs [element :p2] : |
+| params_flow.rb:28:11:28:21 | ...[...] : | semmle.label | ...[...] : |
+| params_flow.rb:29:10:29:22 | ( ... ) | semmle.label | ( ... ) |
+| params_flow.rb:29:11:29:16 | kwargs [element :p3] : | semmle.label | kwargs [element :p3] : |
+| params_flow.rb:29:11:29:21 | ...[...] : | semmle.label | ...[...] : |
+| params_flow.rb:33:12:33:19 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:33:26:33:34 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:33:41:33:49 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:34:14:34:22 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:35:12:35:20 | call to taint : | semmle.label | call to taint : |
+| params_flow.rb:35:23:35:28 | ** ... [element :p3] : | semmle.label | ** ... [element :p3] : |
+| params_flow.rb:35:25:35:28 | args [element :p3] : | semmle.label | args [element :p3] : |
subpaths
#select
| params_flow.rb:10:10:10:11 | p1 | params_flow.rb:14:12:14:19 | call to taint : | params_flow.rb:10:10:10:11 | p1 | $@ | params_flow.rb:14:12:14:19 | call to taint : | call to taint : |
@@ -39,3 +70,8 @@ subpaths
| params_flow.rb:18:10:18:11 | p2 | params_flow.rb:21:27:21:34 | call to taint : | params_flow.rb:18:10:18:11 | p2 | $@ | params_flow.rb:21:27:21:34 | call to taint : | call to taint : |
| params_flow.rb:18:10:18:11 | p2 | params_flow.rb:22:13:22:20 | call to taint : | params_flow.rb:18:10:18:11 | p2 | $@ | params_flow.rb:22:13:22:20 | call to taint : | call to taint : |
| params_flow.rb:18:10:18:11 | p2 | params_flow.rb:23:16:23:23 | call to taint : | params_flow.rb:18:10:18:11 | p2 | $@ | params_flow.rb:23:16:23:23 | call to taint : | call to taint : |
+| params_flow.rb:26:10:26:11 | p1 | params_flow.rb:33:12:33:19 | call to taint : | params_flow.rb:26:10:26:11 | p1 | $@ | params_flow.rb:33:12:33:19 | call to taint : | call to taint : |
+| params_flow.rb:26:10:26:11 | p1 | params_flow.rb:35:12:35:20 | call to taint : | params_flow.rb:26:10:26:11 | p1 | $@ | params_flow.rb:35:12:35:20 | call to taint : | call to taint : |
+| params_flow.rb:28:10:28:22 | ( ... ) | params_flow.rb:33:26:33:34 | call to taint : | params_flow.rb:28:10:28:22 | ( ... ) | $@ | params_flow.rb:33:26:33:34 | call to taint : | call to taint : |
+| params_flow.rb:29:10:29:22 | ( ... ) | params_flow.rb:33:41:33:49 | call to taint : | params_flow.rb:29:10:29:22 | ( ... ) | $@ | params_flow.rb:33:41:33:49 | call to taint : | call to taint : |
+| params_flow.rb:29:10:29:22 | ( ... ) | params_flow.rb:34:14:34:22 | call to taint : | params_flow.rb:29:10:29:22 | ( ... ) | $@ | params_flow.rb:34:14:34:22 | call to taint : | call to taint : |
diff --git a/ruby/ql/test/library-tests/dataflow/params/params_flow.rb b/ruby/ql/test/library-tests/dataflow/params/params_flow.rb
index 27d82148403..d3a99e61f37 100644
--- a/ruby/ql/test/library-tests/dataflow/params/params_flow.rb
+++ b/ruby/ql/test/library-tests/dataflow/params/params_flow.rb
@@ -21,3 +21,15 @@ end
keyword(p1: taint(3), p2: taint(4))
keyword(p2: taint(5), p1: taint(6))
keyword(:p2 => taint(7), :p1 => taint(8))
+
+def kwargs(p1:, **kwargs)
+ sink p1 # $ hasValueFlow=9 $ hasValueFlow=13
+ sink (kwargs[:p1])
+ sink (kwargs[:p2]) # $ hasValueFlow=10
+ sink (kwargs[:p3]) # $ hasValueFlow=11 $ hasValueFlow=12
+ sink (kwargs[:p4])
+end
+
+kwargs(p1: taint(9), p2: taint(10), p3: taint(11), p4: "")
+args = { p3: taint(12), p4: "" }
+kwargs(p1: taint(13), **args)
diff --git a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected
index 564c23d11b0..42d9ec15ec5 100644
--- a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected
+++ b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected
@@ -86,6 +86,12 @@ edges
| summaries.rb:82:1:82:1 | a [element 2] : | summaries.rb:82:1:82:1 | [post] a [element 2] : |
| summaries.rb:85:6:85:6 | a [element 2] : | summaries.rb:85:6:85:9 | ...[...] |
| summaries.rb:85:6:85:6 | a [element 2] : | summaries.rb:85:6:85:9 | ...[...] |
+| summaries.rb:88:1:88:1 | [post] x [@value] : | summaries.rb:89:6:89:6 | x [@value] : |
+| summaries.rb:88:1:88:1 | [post] x [@value] : | summaries.rb:89:6:89:6 | x [@value] : |
+| summaries.rb:88:13:88:26 | call to source : | summaries.rb:88:1:88:1 | [post] x [@value] : |
+| summaries.rb:88:13:88:26 | call to source : | summaries.rb:88:1:88:1 | [post] x [@value] : |
+| summaries.rb:89:6:89:6 | x [@value] : | summaries.rb:89:6:89:16 | call to get_value |
+| summaries.rb:89:6:89:6 | x [@value] : | summaries.rb:89:6:89:16 | call to get_value |
nodes
| summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : |
| summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : |
@@ -183,6 +189,14 @@ nodes
| summaries.rb:85:6:85:6 | a [element 2] : | semmle.label | a [element 2] : |
| summaries.rb:85:6:85:9 | ...[...] | semmle.label | ...[...] |
| summaries.rb:85:6:85:9 | ...[...] | semmle.label | ...[...] |
+| summaries.rb:88:1:88:1 | [post] x [@value] : | semmle.label | [post] x [@value] : |
+| summaries.rb:88:1:88:1 | [post] x [@value] : | semmle.label | [post] x [@value] : |
+| summaries.rb:88:13:88:26 | call to source : | semmle.label | call to source : |
+| summaries.rb:88:13:88:26 | call to source : | semmle.label | call to source : |
+| summaries.rb:89:6:89:6 | x [@value] : | semmle.label | x [@value] : |
+| summaries.rb:89:6:89:6 | x [@value] : | semmle.label | x [@value] : |
+| summaries.rb:89:6:89:16 | call to get_value | semmle.label | call to get_value |
+| summaries.rb:89:6:89:16 | call to get_value | semmle.label | call to get_value |
subpaths
invalidSpecComponent
#select
@@ -227,6 +241,8 @@ invalidSpecComponent
| summaries.rb:80:6:80:9 | ...[...] | summaries.rb:74:15:74:29 | call to source : | summaries.rb:80:6:80:9 | ...[...] | $@ | summaries.rb:74:15:74:29 | call to source : | call to source : |
| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:74:32:74:46 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:74:32:74:46 | call to source : | call to source : |
| summaries.rb:85:6:85:9 | ...[...] | summaries.rb:74:32:74:46 | call to source : | summaries.rb:85:6:85:9 | ...[...] | $@ | summaries.rb:74:32:74:46 | call to source : | call to source : |
+| summaries.rb:89:6:89:16 | call to get_value | summaries.rb:88:13:88:26 | call to source : | summaries.rb:89:6:89:16 | call to get_value | $@ | summaries.rb:88:13:88:26 | call to source : | call to source : |
+| summaries.rb:89:6:89:16 | call to get_value | summaries.rb:88:13:88:26 | call to source : | summaries.rb:89:6:89:16 | call to get_value | $@ | summaries.rb:88:13:88:26 | call to source : | call to source : |
warning
| CSV type row should have 5 columns but has 2: test;TooFewColumns |
| CSV type row should have 5 columns but has 8: test;TooManyColumns;;;Member[Foo].Instance;too;many;columns |
diff --git a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql
index 189403547d9..4f9b344fa78 100644
--- a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql
+++ b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql
@@ -66,6 +66,8 @@ private class StepsFromModel extends ModelInput::SummaryModelCsv {
override predicate row(string row) {
row =
[
+ ";any;Method[set_value];Argument[0];Argument[self].Field[@value];value",
+ ";any;Method[get_value];Argument[self].Field[@value];ReturnValue;value",
";;Member[Foo].Method[firstArg];Argument[0];ReturnValue;taint",
";;Member[Foo].Method[secondArg];Argument[1];ReturnValue;taint",
";;Member[Foo].Method[onlyWithoutBlock].WithoutBlock;Argument[0];ReturnValue;taint",
diff --git a/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb b/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb
index c3b8bec1d01..eadcb57939f 100644
--- a/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb
+++ b/ruby/ql/test/library-tests/dataflow/summaries/summaries.rb
@@ -82,4 +82,8 @@ sink(b[2])
a.withoutElementOne()
sink(a[0])
sink(a[1])
-sink(a[2]) # $ hasValueFlow=elem2
\ No newline at end of file
+sink(a[2]) # $ hasValueFlow=elem2
+
+x = Foo.new
+x.set_value(source("attr"))
+sink(x.get_value) # $ hasValueFlow=attr
\ No newline at end of file
diff --git a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected
index cd548ace1cd..2bb6368f552 100644
--- a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected
+++ b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected
@@ -139,6 +139,7 @@ track
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:31:1:31:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:27:10:27:11 | [post] p2 | type tracker without call steps | type_tracker.rb:27:10:27:11 | [post] p2 |
+| type_tracker.rb:30:1:30:21 | ** | type tracker without call steps | type_tracker.rb:30:1:30:21 | ** |
| type_tracker.rb:30:1:30:21 | [post] self | type tracker with call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:30:1:30:21 | [post] self | type tracker with call steps | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:30:1:30:21 | [post] self | type tracker without call steps | type_tracker.rb:30:1:30:21 | [post] self |
@@ -155,6 +156,7 @@ track
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker without call steps | type_tracker.rb:30:20:30:20 | 4 |
| type_tracker.rb:30:20:30:20 | [post] 4 | type tracker without call steps | type_tracker.rb:30:20:30:20 | [post] 4 |
+| type_tracker.rb:31:1:31:21 | ** | type tracker without call steps | type_tracker.rb:31:1:31:21 | ** |
| type_tracker.rb:31:1:31:21 | [post] self | type tracker with call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:31:1:31:21 | [post] self | type tracker with call steps | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:31:1:31:21 | [post] self | type tracker without call steps | type_tracker.rb:31:1:31:21 | [post] self |
@@ -171,6 +173,7 @@ track
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker without call steps | type_tracker.rb:31:20:31:20 | 6 |
| type_tracker.rb:31:20:31:20 | [post] 6 | type tracker without call steps | type_tracker.rb:31:20:31:20 | [post] 6 |
+| type_tracker.rb:32:1:32:27 | ** | type tracker without call steps | type_tracker.rb:32:1:32:27 | ** |
| type_tracker.rb:32:1:32:27 | [post] self | type tracker without call steps | type_tracker.rb:32:1:32:27 | [post] self |
| type_tracker.rb:32:1:32:27 | call to keyword | type tracker without call steps | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:32:9:32:11 | :p2 | type tracker without call steps | type_tracker.rb:32:9:32:11 | :p2 |
@@ -393,6 +396,7 @@ trackEnd
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:31:1:31:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:27:10:27:11 | [post] p2 | type_tracker.rb:27:10:27:11 | [post] p2 |
+| type_tracker.rb:30:1:30:21 | ** | type_tracker.rb:30:1:30:21 | ** |
| type_tracker.rb:30:1:30:21 | [post] self | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:30:1:30:21 | [post] self | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:30:1:30:21 | [post] self | type_tracker.rb:26:5:26:11 | self |
@@ -415,6 +419,7 @@ trackEnd
| type_tracker.rb:30:20:30:20 | 4 | type_tracker.rb:27:10:27:11 | p2 |
| type_tracker.rb:30:20:30:20 | 4 | type_tracker.rb:30:20:30:20 | 4 |
| type_tracker.rb:30:20:30:20 | [post] 4 | type_tracker.rb:30:20:30:20 | [post] 4 |
+| type_tracker.rb:31:1:31:21 | ** | type_tracker.rb:31:1:31:21 | ** |
| type_tracker.rb:31:1:31:21 | [post] self | type_tracker.rb:25:1:28:3 | self (keyword) |
| type_tracker.rb:31:1:31:21 | [post] self | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:31:1:31:21 | [post] self | type_tracker.rb:26:5:26:11 | self |
@@ -436,6 +441,7 @@ trackEnd
| type_tracker.rb:31:20:31:20 | 6 | type_tracker.rb:26:10:26:11 | p1 |
| type_tracker.rb:31:20:31:20 | 6 | type_tracker.rb:31:20:31:20 | 6 |
| type_tracker.rb:31:20:31:20 | [post] 6 | type_tracker.rb:31:20:31:20 | [post] 6 |
+| type_tracker.rb:32:1:32:27 | ** | type_tracker.rb:32:1:32:27 | ** |
| type_tracker.rb:32:1:32:27 | [post] self | type_tracker.rb:32:1:32:27 | [post] self |
| type_tracker.rb:32:1:32:27 | call to keyword | type_tracker.rb:32:1:32:27 | call to keyword |
| type_tracker.rb:32:9:32:11 | :p2 | type_tracker.rb:32:9:32:11 | :p2 |
diff --git a/ruby/ql/test/library-tests/experimental/Rbi.expected b/ruby/ql/test/library-tests/experimental/Rbi.expected
new file mode 100644
index 00000000000..355c9db3beb
--- /dev/null
+++ b/ruby/ql/test/library-tests/experimental/Rbi.expected
@@ -0,0 +1,122 @@
+rbiTypes
+| test_types.rb:7:17:7:23 | Integer |
+| test_types.rb:10:19:10:25 | Integer |
+| test_types.rb:10:31:10:37 | Integer |
+| test_types.rb:10:48:10:54 | Integer |
+| test_types.rb:13:19:13:25 | Integer |
+| test_types.rb:13:36:13:36 | T |
+| test_types.rb:13:36:13:45 | Boolean |
+| test_types.rb:18:17:18:23 | MyClass |
+| test_types.rb:21:17:21:22 | String |
+| test_types.rb:24:17:24:23 | Integer |
+| test_types.rb:29:10:29:15 | String |
+| test_types.rb:30:14:30:14 | T |
+| test_types.rb:30:14:30:54 | call to nilable |
+| test_types.rb:30:24:30:24 | T |
+| test_types.rb:30:24:30:29 | call to proc |
+| test_types.rb:30:24:30:48 | call to params |
+| test_types.rb:30:24:30:53 | call to void |
+| test_types.rb:30:41:30:47 | Integer |
+| test_types.rb:37:10:37:15 | String |
+| test_types.rb:38:14:38:14 | T |
+| test_types.rb:38:14:38:19 | call to proc |
+| test_types.rb:38:14:38:38 | call to params |
+| test_types.rb:38:14:38:54 | call to returns |
+| test_types.rb:38:31:38:37 | Integer |
+| test_types.rb:38:48:38:53 | String |
+| test_types.rb:43:22:43:22 | T |
+| test_types.rb:43:22:43:28 | Hash |
+| test_types.rb:43:30:43:30 | T |
+| test_types.rb:43:30:43:38 | call to untyped |
+| test_types.rb:43:41:43:41 | T |
+| test_types.rb:43:41:43:49 | call to untyped |
+| test_types.rb:46:21:46:21 | T |
+| test_types.rb:46:21:46:28 | Array |
+| test_types.rb:46:30:46:35 | Symbol |
+| test_types.rb:49:26:49:26 | T |
+| test_types.rb:49:26:49:46 | call to any |
+| test_types.rb:49:32:49:37 | String |
+| test_types.rb:49:40:49:45 | Symbol |
+| test_types.rb:49:57:49:62 | String |
+| test_types.rb:52:23:52:23 | T |
+| test_types.rb:52:23:52:32 | Boolean |
+| test_types.rb:52:43:52:43 | T |
+| test_types.rb:52:43:52:52 | Boolean |
+unionTypes
+| test_types.rb:49:26:49:46 | call to any | test_types.rb:49:32:49:37 | String |
+| test_types.rb:49:26:49:46 | call to any | test_types.rb:49:40:49:45 | Symbol |
+nilableTypes
+| test_types.rb:30:14:30:54 | call to nilable | test_types.rb:30:24:30:53 | call to void |
+typeAliases
+arrayTypes
+| test_types.rb:46:21:46:28 | Array | test_types.rb:46:30:46:35 | Symbol |
+hashTypes
+| test_types.rb:43:22:43:28 | Hash | test_types.rb:43:30:43:38 | call to untyped | test_types.rb:43:41:43:49 | call to untyped |
+signatureCalls
+| test_types.rb:4:3:4:14 | call to sig | (void) |
+| test_types.rb:7:3:7:26 | call to sig | Integer |
+| test_types.rb:10:3:10:57 | call to sig | Integer |
+| test_types.rb:13:3:13:48 | call to sig | Boolean |
+| test_types.rb:18:3:18:26 | call to sig | MyClass |
+| test_types.rb:21:3:21:25 | call to sig | String |
+| test_types.rb:24:3:24:26 | call to sig | Integer |
+| test_types.rb:27:3:32:5 | call to sig | (void) |
+| test_types.rb:30:24:30:29 | call to proc | (void) |
+| test_types.rb:38:14:38:19 | call to proc | String |
+| test_types.rb:43:3:43:58 | call to sig | (void) |
+| test_types.rb:49:3:49:65 | call to sig | String |
+| test_types.rb:52:3:52:55 | call to sig | Boolean |
+paramsCalls
+| test_types.rb:10:9:10:38 | call to params |
+| test_types.rb:13:9:13:26 | call to params |
+| test_types.rb:28:5:31:5 | call to params |
+| test_types.rb:30:24:30:48 | call to params |
+| test_types.rb:36:5:39:5 | call to params |
+| test_types.rb:38:14:38:38 | call to params |
+| test_types.rb:43:9:43:51 | call to params |
+| test_types.rb:46:9:46:37 | call to params |
+| test_types.rb:49:9:49:47 | call to params |
+| test_types.rb:52:9:52:33 | call to params |
+returnsCall
+| test_types.rb:7:9:7:24 | call to returns | Integer |
+| test_types.rb:10:9:10:55 | call to returns | Integer |
+| test_types.rb:13:9:13:46 | call to returns | Boolean |
+| test_types.rb:18:9:18:24 | call to returns | MyClass |
+| test_types.rb:21:9:21:23 | call to returns | String |
+| test_types.rb:24:9:24:24 | call to returns | Integer |
+| test_types.rb:38:14:38:54 | call to returns | String |
+| test_types.rb:49:9:49:63 | call to returns | String |
+| test_types.rb:52:9:52:53 | call to returns | Boolean |
+voidCall
+| test_types.rb:4:9:4:12 | call to void |
+| test_types.rb:28:5:31:10 | call to void |
+| test_types.rb:30:24:30:53 | call to void |
+| test_types.rb:43:9:43:56 | call to void |
+parameterTypes
+| test_types.rb:10:16:10:25 | Pair | test_types.rb:11:11:11:11 | a | test_types.rb:10:19:10:25 | Integer |
+| test_types.rb:10:28:10:37 | Pair | test_types.rb:11:14:11:14 | b | test_types.rb:10:31:10:37 | Integer |
+| test_types.rb:13:16:13:25 | Pair | test_types.rb:14:18:14:18 | a | test_types.rb:13:19:13:25 | Integer |
+| test_types.rb:29:7:29:15 | Pair | test_types.rb:33:26:33:26 | a | test_types.rb:29:10:29:15 | String |
+| test_types.rb:30:7:30:54 | Pair | test_types.rb:33:29:33:34 | &block | test_types.rb:30:14:30:54 | call to nilable |
+| test_types.rb:37:7:37:15 | Pair | test_types.rb:41:18:41:18 | a | test_types.rb:37:10:37:15 | String |
+| test_types.rb:38:7:38:54 | Pair | test_types.rb:41:21:41:26 | &block | test_types.rb:38:14:38:54 | call to returns |
+| test_types.rb:49:16:49:46 | Pair | test_types.rb:50:14:50:21 | new_name | test_types.rb:49:26:49:46 | call to any |
+| test_types.rb:52:16:52:32 | Pair | test_types.rb:53:24:53:28 | value | test_types.rb:52:23:52:32 | Boolean |
+procParameterTypes
+| test_types.rb:30:7:30:54 | Pair | test_types.rb:30:24:30:53 | call to void | test_types.rb:30:24:30:29 | call to proc | nilable |
+| test_types.rb:38:7:38:54 | Pair | test_types.rb:38:14:38:54 | call to returns | test_types.rb:38:14:38:19 | call to proc | non_nilable |
+sigMethods
+| test_types.rb:4:3:4:14 | call to sig | test_types.rb:5:3:5:30 | perform_some_action |
+| test_types.rb:7:3:7:26 | call to sig | test_types.rb:8:3:8:21 | return_one |
+| test_types.rb:10:3:10:57 | call to sig | test_types.rb:11:3:11:20 | add |
+| test_types.rb:13:3:13:48 | call to sig | test_types.rb:14:3:14:24 | isPositive |
+| test_types.rb:18:3:18:26 | call to sig | test_types.rb:19:3:19:31 | getMyClassInstance |
+| test_types.rb:27:3:32:5 | call to sig | test_types.rb:33:3:33:40 | blk_nilable_method |
+| test_types.rb:35:3:40:5 | call to sig | test_types.rb:41:3:41:32 | blk_method |
+| test_types.rb:43:3:43:58 | call to sig | test_types.rb:44:3:44:28 | read_hash |
+| test_types.rb:46:3:46:39 | call to sig | test_types.rb:47:3:47:34 | read_symbol_array |
+| test_types.rb:49:3:49:65 | call to sig | test_types.rb:50:3:50:27 | rename |
+| test_types.rb:52:3:52:55 | call to sig | test_types.rb:53:3:53:34 | debug_mode= |
+sigAttrReaders
+| test_types.rb:21:3:21:25 | call to sig | test_types.rb:22:3:22:26 | call to attr_reader |
+| test_types.rb:24:3:24:26 | call to sig | test_types.rb:25:3:25:24 | call to attr_accessor |
diff --git a/ruby/ql/test/library-tests/experimental/Rbi.ql b/ruby/ql/test/library-tests/experimental/Rbi.ql
new file mode 100644
index 00000000000..6a079008273
--- /dev/null
+++ b/ruby/ql/test/library-tests/experimental/Rbi.ql
@@ -0,0 +1,48 @@
+private import codeql.ruby.AST
+private import codeql.ruby.experimental.Rbi::Rbi
+
+query predicate rbiTypes(RbiType t) { any() }
+
+query predicate unionTypes(RbiUnionType t, RbiType u) { u = t.getAType() }
+
+query predicate nilableTypes(RbiNilableType t, RbiType u) { u = t.getUnderlyingType() }
+
+query predicate typeAliases(RbiTypeAlias a, RbiType t) { t = a.getAliasedType() }
+
+query predicate arrayTypes(RbiArrayType at, RbiType et) { et = at.getElementType() }
+
+query predicate hashTypes(RbiHashType ht, RbiType kt, RbiType vt) {
+ kt = ht.getKeyType() and vt = ht.getValueType()
+}
+
+query predicate signatureCalls(SignatureCall c, ReturnType r) { r = c.getReturnType() }
+
+query predicate paramsCalls(ParamsCall c) { any() }
+
+query predicate returnsCall(ReturnsCall c, ReturnType r) { r = c.getReturnType() }
+
+query predicate voidCall(VoidCall c) { any() }
+
+query predicate parameterTypes(ParameterType pt, NamedParameter p, RbiType t) {
+ p = pt.getParameter() and t = pt.getType()
+}
+
+query predicate procParameterTypes(
+ ParameterType pt, ProcReturnsTypeCall prtc, ProcCall pc, string isNilable
+) {
+ (
+ exists(RbiNilableType nilable | nilable = pt.getType() |
+ prtc = nilable.getUnderlyingType() and
+ isNilable = "nilable"
+ )
+ or
+ pt.getType() = prtc and isNilable = "non_nilable"
+ ) and
+ pc = prtc.getProcCall()
+}
+
+query predicate sigMethods(MethodSignatureCall sig, MethodBase m) { m = sig.getAssociatedMethod() }
+
+query predicate sigAttrReaders(MethodSignatureCall sig, MethodCall attr_reader) {
+ attr_reader = sig.getAssociatedAttrReaderCall()
+}
diff --git a/ruby/ql/test/library-tests/experimental/test_types.rb b/ruby/ql/test/library-tests/experimental/test_types.rb
new file mode 100644
index 00000000000..67308db1c2d
--- /dev/null
+++ b/ruby/ql/test/library-tests/experimental/test_types.rb
@@ -0,0 +1,54 @@
+# TODO: this should be a .rbi file if we decide to extract them by default
+
+module TestTypes
+ sig { void }
+ def perform_some_action; end
+
+ sig { returns(Integer) }
+ def return_one; end
+
+ sig { params(a: Integer, b: Integer).returns(Integer) }
+ def add(a, b); end
+
+ sig { params(a: Integer).returns(T::Boolean) }
+ def isPositive(a); end
+
+ class MyClass; end
+
+ sig { returns(MyClass) }
+ def getMyClassInstance(); end
+
+ sig { returns(String) }
+ attr_reader :name, :kind
+
+ sig { returns(Integer) }
+ attr_accessor :version
+
+ sig do
+ params(
+ a: String,
+ block: T.nilable(T.proc.params(b: Integer).void)
+ ).void
+ end
+ def blk_nilable_method(a, &block); end
+
+ sig do
+ params(
+ a: String,
+ block: T.proc.params(b: Integer).returns(String)
+ )
+ end
+ def blk_method(a, &block); end
+
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).void }
+ def read_hash(**hash); end
+
+ sig { params(arr: T::Array[Symbol]) }
+ def read_symbol_array(*arr); end
+
+ sig { params(new_name: T.any(String, Symbol)).returns(String) }
+ def rename(new_name); end
+
+ sig { params(value: T::Boolean).returns(T::Boolean) }
+ def self.debug_mode=(value); end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/ActiveRecord.expected b/ruby/ql/test/library-tests/frameworks/ActiveRecord.expected
index a18e9fa1167..0c2286528bd 100644
--- a/ruby/ql/test/library-tests/frameworks/ActiveRecord.expected
+++ b/ruby/ql/test/library-tests/frameworks/ActiveRecord.expected
@@ -2,6 +2,14 @@ activeRecordModelClasses
| ActiveRecordInjection.rb:1:1:3:3 | UserGroup |
| ActiveRecordInjection.rb:5:1:17:3 | User |
| ActiveRecordInjection.rb:19:1:25:3 | Admin |
+activeRecordInstances
+| ActiveRecordInjection.rb:10:5:10:68 | call to find |
+| ActiveRecordInjection.rb:15:5:15:40 | call to find_by |
+| ActiveRecordInjection.rb:79:5:81:7 | if ... |
+| ActiveRecordInjection.rb:79:43:80:40 | then ... |
+| ActiveRecordInjection.rb:80:7:80:40 | call to find_by |
+| ActiveRecordInjection.rb:85:5:85:33 | call to find_by |
+| ActiveRecordInjection.rb:88:5:88:34 | call to find |
activeRecordSqlExecutionRanges
| ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" |
| ActiveRecordInjection.rb:23:16:23:24 | condition |
@@ -45,9 +53,8 @@ potentiallyUnsafeSqlExecutingMethodCall
| ActiveRecordInjection.rb:75:5:75:29 | call to order |
| ActiveRecordInjection.rb:80:7:80:40 | call to find_by |
activeRecordModelInstantiations
-| ActiveRecordInjection.rb:8:3:11:5 | self (authenticate) | ActiveRecordInjection.rb:5:1:17:3 | User |
+| ActiveRecordInjection.rb:10:5:10:68 | call to find | ActiveRecordInjection.rb:5:1:17:3 | User |
| ActiveRecordInjection.rb:15:5:15:40 | call to find_by | ActiveRecordInjection.rb:1:1:3:3 | UserGroup |
-| ActiveRecordInjection.rb:20:3:24:5 | self (delete_by) | ActiveRecordInjection.rb:19:1:25:3 | Admin |
| ActiveRecordInjection.rb:80:7:80:40 | call to find_by | ActiveRecordInjection.rb:5:1:17:3 | User |
| ActiveRecordInjection.rb:85:5:85:33 | call to find_by | ActiveRecordInjection.rb:5:1:17:3 | User |
| ActiveRecordInjection.rb:88:5:88:34 | call to find | ActiveRecordInjection.rb:5:1:17:3 | User |
diff --git a/ruby/ql/test/library-tests/frameworks/ActiveRecord.ql b/ruby/ql/test/library-tests/frameworks/ActiveRecord.ql
index f7ce327b95a..6d19f9bb9ec 100644
--- a/ruby/ql/test/library-tests/frameworks/ActiveRecord.ql
+++ b/ruby/ql/test/library-tests/frameworks/ActiveRecord.ql
@@ -3,6 +3,8 @@ import codeql.ruby.frameworks.ActiveRecord
query predicate activeRecordModelClasses(ActiveRecordModelClass cls) { any() }
+query predicate activeRecordInstances(ActiveRecordInstance i) { any() }
+
query predicate activeRecordSqlExecutionRanges(ActiveRecordSqlExecutionRange range) { any() }
query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) { any() }
diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
index 6118b4b20c6..9022e848300 100644
--- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
+++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
@@ -12,6 +12,9 @@ edges
| CommandInjection.rb:46:15:46:26 | ...[...] : | CommandInjection.rb:50:24:50:36 | "echo #{...}" |
| CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" |
| CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" |
+| CommandInjection.rb:81:20:81:25 | **args : | CommandInjection.rb:82:22:82:25 | args : |
+| CommandInjection.rb:82:22:82:25 | args : | CommandInjection.rb:82:22:82:37 | ...[...] : |
+| CommandInjection.rb:82:22:82:37 | ...[...] : | CommandInjection.rb:82:14:82:39 | "echo #{...}" |
nodes
| CommandInjection.rb:6:15:6:20 | call to params : | semmle.label | call to params : |
| CommandInjection.rb:6:15:6:26 | ...[...] : | semmle.label | ...[...] : |
@@ -30,6 +33,10 @@ nodes
| CommandInjection.rb:65:14:65:29 | "echo #{...}" | semmle.label | "echo #{...}" |
| CommandInjection.rb:72:23:72:33 | blah_number : | semmle.label | blah_number : |
| CommandInjection.rb:73:14:73:34 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:81:20:81:25 | **args : | semmle.label | **args : |
+| CommandInjection.rb:82:14:82:39 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:82:22:82:25 | args : | semmle.label | args : |
+| CommandInjection.rb:82:22:82:37 | ...[...] : | semmle.label | ...[...] : |
subpaths
#select
| CommandInjection.rb:7:10:7:15 | #{...} | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:7:10:7:15 | #{...} | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
@@ -43,3 +50,4 @@ subpaths
| CommandInjection.rb:50:24:50:36 | "echo #{...}" | CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:50:24:50:36 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:46:15:46:20 | call to params | a user-provided value |
| CommandInjection.rb:65:14:65:29 | "echo #{...}" | CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:64:18:64:23 | number | a user-provided value |
| CommandInjection.rb:73:14:73:34 | "echo #{...}" | CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:72:23:72:33 | blah_number | a user-provided value |
+| CommandInjection.rb:82:14:82:39 | "echo #{...}" | CommandInjection.rb:81:20:81:25 | **args : | CommandInjection.rb:82:14:82:39 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:81:20:81:25 | **args | a user-provided value |
diff --git a/swift/codegen/schema.yml b/swift/codegen/schema.yml
index 03cdf16c208..ebdece63965 100644
--- a/swift/codegen/schema.yml
+++ b/swift/codegen/schema.yml
@@ -63,6 +63,7 @@ AnyFunctionType:
param_types: Type*
param_labels: string*
is_throwing: predicate
+ is_async: predicate
AnyGenericType:
_extends: Type
diff --git a/swift/extractor/visitors/TypeVisitor.h b/swift/extractor/visitors/TypeVisitor.h
index 21c6978e325..3299d09eb8c 100644
--- a/swift/extractor/visitors/TypeVisitor.h
+++ b/swift/extractor/visitors/TypeVisitor.h
@@ -211,6 +211,14 @@ class TypeVisitor : public TypeVisitorBase {
}
++i;
}
+
+ if (type->isThrowing()) {
+ dispatcher_.emit(AnyFunctionTypeIsThrowingTrap{label});
+ }
+
+ if (type->isAsync()) {
+ dispatcher_.emit(AnyFunctionTypeIsAsyncTrap{label});
+ }
}
void emitBoundGenericType(swift::BoundGenericType* type, TrapLabel label) {
diff --git a/swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll b/swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll
index dd021a41ddf..462af68202f 100644
--- a/swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll
@@ -3,6 +3,7 @@
private import swift
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
+private import internal.ControlFlowElements
private import CfgNodes
private import SuccessorTypes
@@ -198,8 +199,18 @@ private module JoinBlockPredecessors {
private predicate idOf(AstNode x, int y) = equivalenceRelation(id/2)(x, y)
+ private AstNode projctToAst(ControlFlowElement n) {
+ result = n.asAstNode()
+ or
+ isPropertyGetterElement(n, _, result)
+ or
+ isPropertySetterElement(n, _, result)
+ or
+ isPropertyObserverElement(n, _, result)
+ }
+
int getId(JoinBlockPredecessor jbp) {
- idOf(jbp.getFirstNode().(AstCfgNode).getNode(), result)
+ idOf(projctToAst(jbp.getFirstNode().(AstCfgNode).getNode()), result)
or
idOf(jbp.(EntryBasicBlock).getScope(), result)
}
diff --git a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll
index 1833089896c..6c9f3206e04 100644
--- a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll
@@ -4,6 +4,7 @@ private import swift
private import BasicBlocks
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
+private import internal.ControlFlowElements
private import internal.Splitting
/** An entry node for a given scope. */
@@ -66,11 +67,11 @@ class ExitNode extends ControlFlowNode, TExitNode {
*/
class AstCfgNode extends ControlFlowNode, TElementNode {
private Splits splits;
- private AstNode n;
+ private ControlFlowElement n;
AstCfgNode() { this = TElementNode(_, n, splits) }
- final override AstNode getNode() { result = n }
+ final override ControlFlowElement getNode() { result = n }
override Location getLocation() { result = n.getLocation() }
@@ -96,7 +97,7 @@ class AstCfgNode extends ControlFlowNode, TElementNode {
class ExprCfgNode extends AstCfgNode {
Expr e;
- ExprCfgNode() { e = this.getNode() }
+ ExprCfgNode() { e = this.getNode().asAstNode() }
/** Gets the underlying expression. */
Expr getExpr() { result = e }
diff --git a/swift/ql/lib/codeql/swift/controlflow/ControlFlowGraph.qll b/swift/ql/lib/codeql/swift/controlflow/ControlFlowGraph.qll
index a54043499d6..d6eec89d939 100644
--- a/swift/ql/lib/codeql/swift/controlflow/ControlFlowGraph.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/ControlFlowGraph.qll
@@ -6,13 +6,14 @@ private import SuccessorTypes
private import internal.ControlFlowGraphImpl
private import internal.Completion
private import internal.Scope
+private import internal.ControlFlowElements
/** An AST node with an associated control-flow graph. */
class CfgScope extends Scope instanceof CfgScope::Range_ {
/** Gets the CFG scope that this scope is nested under, if any. */
final CfgScope getOuterCfgScope() {
- exists(AstNode parent |
- parent = getParent(this) and
+ exists(ControlFlowElement parent |
+ parent.asAstNode() = getParentOfAst(this) and
result = getCfgScope(parent)
)
}
@@ -31,7 +32,7 @@ class ControlFlowNode extends TCfgNode {
string toString() { none() }
/** Gets the AST node that this node corresponds to, if any. */
- AstNode getNode() { none() }
+ ControlFlowElement getNode() { none() }
/** Gets the location of this control flow node. */
Location getLocation() { none() }
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/AstControlFlowTrees.qll b/swift/ql/lib/codeql/swift/controlflow/internal/AstControlFlowTrees.qll
new file mode 100644
index 00000000000..0fdf4d1735a
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/AstControlFlowTrees.qll
@@ -0,0 +1,40 @@
+private import swift
+private import Completion
+private import ControlFlowGraphImplShared
+private import ControlFlowElements
+
+abstract class AstControlFlowTree extends ControlFlowTree {
+ AstNode ast;
+
+ AstControlFlowTree() { ast = this.asAstNode() }
+
+ AstNode getAst() { result = ast }
+}
+
+/**
+ * Holds if `first` is the first element executed within control flow
+ * element `cft`.
+ */
+predicate astFirst(AstNode cft, ControlFlowElement first) {
+ first(any(ControlFlowTree tree | cft = tree.asAstNode()), first)
+}
+
+/**
+ * Holds if `last` with completion `c` is a potential last element executed
+ * within control flow element `cft`.
+ */
+predicate astLast(AstNode cft, ControlFlowElement last, Completion c) {
+ last(any(ControlFlowTree tree | cft = tree.asAstNode()), last, c)
+}
+
+abstract class AstPreOrderTree extends AstControlFlowTree, PreOrderTree { }
+
+abstract class AstPostOrderTree extends AstControlFlowTree, PostOrderTree { }
+
+abstract class AstStandardTree extends AstControlFlowTree, StandardTree { }
+
+abstract class AstStandardPreOrderTree extends AstStandardTree, StandardPreOrderTree { }
+
+abstract class AstStandardPostOrderTree extends AstStandardTree, StandardPostOrderTree { }
+
+abstract class AstLeafTree extends AstPreOrderTree, AstPostOrderTree, LeafTree { }
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll
index 8180e75f2f9..dd3d3219453 100644
--- a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll
@@ -6,6 +6,7 @@
private import swift
private import codeql.swift.controlflow.ControlFlowGraph
+private import ControlFlowElements
private import ControlFlowGraphImpl
private import SuccessorTypes
@@ -41,8 +42,8 @@ private predicate completionIsValidForStmt(Stmt stmt, Completion c) {
/** A completion of a statement or an expression. */
abstract class Completion extends TCompletion {
- private predicate isValidForSpecific(AstNode n) {
- completionIsValidForStmt(n, this)
+ private predicate isValidForSpecific(ControlFlowElement n) {
+ completionIsValidForStmt(n.asAstNode(), this)
or
mustHaveBooleanCompletion(n) and
(
@@ -52,22 +53,24 @@ abstract class Completion extends TCompletion {
this = TBooleanCompletion(_)
)
or
- mustHaveMatchingCompletion(n) and
+ mustHaveMatchingCompletion(n.asAstNode()) and
(
- exists(boolean value | isMatchingConstant(n, value) | this = TMatchingCompletion(value))
+ exists(boolean value | isMatchingConstant(n.asAstNode(), value) |
+ this = TMatchingCompletion(value)
+ )
or
- not isMatchingConstant(n, _) and
+ not isMatchingConstant(n.asAstNode(), _) and
this = TMatchingCompletion(_)
)
or
- mustHaveThrowCompletion(n, this)
+ mustHaveThrowCompletion(n.asAstNode(), this)
}
/** Holds if this completion is valid for node `n`. */
- predicate isValidFor(AstNode n) {
+ predicate isValidFor(ControlFlowElement n) {
this.isValidForSpecific(n)
or
- mayHaveThrowCompletion(n, this)
+ mayHaveThrowCompletion(n.asAstNode(), this)
or
not any(Completion c).isValidForSpecific(n) and
this = TSimpleCompletion()
@@ -87,25 +90,35 @@ abstract class Completion extends TCompletion {
}
/** Holds if node `n` has the Boolean constant value `value`. */
-private predicate isBooleanConstant(AstNode n, boolean value) {
+private predicate isBooleanConstant(ControlFlowElement n, boolean value) {
mustHaveBooleanCompletion(n) and
- value = n.(BooleanLiteralExpr).getValue()
+ value = n.asAstNode().(BooleanLiteralExpr).getValue()
or
// Boolean consants hidden inside conversions are also
// constants that resolve to the same value.
- isBooleanConstant(n.getResolveStep(), value)
+ exists(ControlFlowElement parent |
+ parent.asAstNode() = n.asAstNode().getResolveStep() and
+ isBooleanConstant(parent, value)
+ )
}
/**
* Holds if a normal completion of `n` must be a Boolean completion.
*/
-private predicate mustHaveBooleanCompletion(AstNode n) { inBooleanContext(n) }
+private predicate mustHaveBooleanCompletion(ControlFlowElement n) { inBooleanContext(n) }
/**
* Holds if `n` is used in a Boolean context. That is, the value
* that `n` evaluates to determines a true/false branch successor.
*/
-private predicate inBooleanContext(AstNode n) {
+private predicate inBooleanContext(ControlFlowElement n) {
+ astInBooleanContext(n.asAstNode()) or
+ astInBooleanContext(n.(PropertyGetterElement).getRef()) or
+ astInBooleanContext(n.(PropertySetterElement).getAssignExpr()) or
+ astInBooleanContext(n.(PropertyObserverElement).getAssignExpr())
+}
+
+private predicate astInBooleanContext(AstNode n) {
n = any(ConditionElement condElem).getFullyUnresolved()
or
n = any(StmtCondition stmtCond).getFullyUnresolved()
@@ -115,30 +128,30 @@ private predicate inBooleanContext(AstNode n) {
exists(LogicalAndExpr parent |
n = parent.getLeftOperand().getFullyConverted()
or
- inBooleanContext(parent) and
+ astInBooleanContext(parent) and
n = parent.getRightOperand().getFullyConverted()
)
or
exists(LogicalOrExpr parent |
n = parent.getLeftOperand().getFullyConverted()
or
- inBooleanContext(parent) and
+ astInBooleanContext(parent) and
n = parent.getRightOperand().getFullyConverted()
)
or
- n = any(NotExpr parent | inBooleanContext(parent)).getOperand().getFullyConverted()
+ n = any(NotExpr parent | astInBooleanContext(parent)).getOperand().getFullyConverted()
or
exists(IfExpr ifExpr |
ifExpr.getCondition().getFullyConverted() = n
or
- inBooleanContext(ifExpr) and
+ astInBooleanContext(ifExpr) and
n = ifExpr.getBranch(_).getFullyConverted()
)
or
exists(ForEachStmt foreach | n = foreach.getWhere().getFullyConverted())
or
exists(Exprs::Conversions::ConversionOrIdentityTree parent |
- inBooleanContext(parent) and
+ astInBooleanContext(parent.getAst()) and
parent.convertsFrom(n)
)
}
@@ -477,3 +490,18 @@ class ThrowCompletion extends TThrowCompletion, Completion {
override string toString() { result = "throw" }
}
+
+/**
+ * Hold if `c` represents normal evaluation of a statement or an
+ * expression.
+ */
+predicate completionIsNormal(Completion c) { c instanceof NormalCompletion }
+
+/**
+ * Hold if `c` represents simple (normal) evaluation of a statement or an
+ * expression.
+ */
+predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
+
+/** Holds if `c` is a valid completion for `e`. */
+predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) }
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll
new file mode 100644
index 00000000000..b5557c71e86
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll
@@ -0,0 +1,163 @@
+private import swift
+
+cached
+newtype TControlFlowElement =
+ TAstElement(AstNode n) or
+ TPropertyGetterElement(Decl accessor, Expr ref) { isPropertyGetterElement(accessor, ref) } or
+ TPropertySetterElement(AccessorDecl accessor, AssignExpr assign) {
+ isPropertySetterElement(accessor, assign)
+ } or
+ TPropertyObserverElement(AccessorDecl observer, AssignExpr assign) {
+ isPropertyObserverElement(observer, assign)
+ }
+
+predicate isLValue(Expr e) { any(AssignExpr assign).getDest() = e }
+
+predicate isRValue(Expr e) { not isLValue(e) }
+
+predicate ignoreAstElement(AstNode n) {
+ isPropertyGetterElement(_, n)
+ or
+ isPropertySetterElement(_, n)
+}
+
+private AccessorDecl getAnAccessorDecl(Decl d) {
+ result = d.(VarDecl).getAnAccessorDecl() or
+ result = d.(SubscriptDecl).getAnAccessorDecl()
+}
+
+predicate isPropertyGetterElement(AccessorDecl accessor, Expr ref) {
+ hasDirectToImplementationOrOrdinarySemantics(ref) and
+ isRValue(ref) and
+ accessor.isGetter() and
+ accessor = getAnAccessorDecl([ref.(LookupExpr).getMember(), ref.(DeclRefExpr).getDecl()])
+}
+
+predicate isPropertyGetterElement(PropertyGetterElement pge, AccessorDecl accessor, Expr ref) {
+ pge = TPropertyGetterElement(accessor, ref)
+}
+
+private predicate hasDirectToImplementationSemantics(Expr e) {
+ e.(MemberRefExpr).hasDirectToImplementationSemantics()
+ or
+ e.(SubscriptExpr).hasDirectToImplementationSemantics()
+ or
+ e.(DeclRefExpr).hasDirectToImplementationSemantics()
+}
+
+private predicate hasOrdinarySemantics(Expr e) {
+ e.(MemberRefExpr).hasOrdinarySemantics()
+ or
+ e.(SubscriptExpr).hasOrdinarySemantics()
+ or
+ e.(DeclRefExpr).hasOrdinarySemantics()
+}
+
+private predicate hasDirectToImplementationOrOrdinarySemantics(Expr e) {
+ hasDirectToImplementationSemantics(e) or hasOrdinarySemantics(e)
+}
+
+private predicate isPropertySetterElement(AccessorDecl accessor, AssignExpr assign) {
+ exists(Expr lhs | lhs = assign.getDest() |
+ hasDirectToImplementationOrOrdinarySemantics(lhs) and
+ accessor.isSetter() and
+ isLValue(lhs) and
+ accessor = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()])
+ )
+}
+
+predicate isPropertySetterElement(
+ PropertySetterElement pse, AccessorDecl accessor, AssignExpr assign
+) {
+ pse = TPropertySetterElement(accessor, assign)
+}
+
+private predicate isPropertyObserverElement(AccessorDecl observer, AssignExpr assign) {
+ exists(Expr lhs | lhs = assign.getDest() |
+ hasDirectToImplementationOrOrdinarySemantics(lhs) and
+ observer.isPropertyObserver() and
+ isLValue(lhs) and
+ observer = getAnAccessorDecl([lhs.(LookupExpr).getMember(), lhs.(DeclRefExpr).getDecl()])
+ )
+}
+
+predicate isPropertyObserverElement(
+ PropertyObserverElement poe, AccessorDecl accessor, AssignExpr assign
+) {
+ poe = TPropertyObserverElement(accessor, assign)
+}
+
+class ControlFlowElement extends TControlFlowElement {
+ string toString() { none() } // overriden in subclasses
+
+ AstNode asAstNode() { none() }
+
+ Location getLocation() { none() } // overriden in subclasses
+}
+
+class AstElement extends ControlFlowElement, TAstElement {
+ AstNode n;
+
+ AstElement() { this = TAstElement(n) }
+
+ override string toString() { result = n.toString() }
+
+ override AstNode asAstNode() { result = n }
+
+ override Location getLocation() { result = n.getLocation() }
+}
+
+class PropertyGetterElement extends ControlFlowElement, TPropertyGetterElement {
+ AccessorDecl accessor;
+ Expr ref;
+
+ PropertyGetterElement() { this = TPropertyGetterElement(accessor, ref) }
+
+ override string toString() { result = "getter for " + ref.toString() }
+
+ override Location getLocation() { result = ref.getLocation() }
+
+ Expr getRef() { result = ref }
+
+ AccessorDecl getAccessorDecl() { result = accessor }
+}
+
+class PropertySetterElement extends ControlFlowElement, TPropertySetterElement {
+ AccessorDecl accessor;
+ AssignExpr assign;
+
+ PropertySetterElement() { this = TPropertySetterElement(accessor, assign) }
+
+ override string toString() { result = "setter for " + assign }
+
+ override Location getLocation() { result = assign.getLocation() }
+
+ AccessorDecl getAccessorDecl() { result = accessor }
+
+ AssignExpr getAssignExpr() { result = assign }
+}
+
+class PropertyObserverElement extends ControlFlowElement, TPropertyObserverElement {
+ AccessorDecl observer;
+ AssignExpr assign;
+
+ PropertyObserverElement() { this = TPropertyObserverElement(observer, assign) }
+
+ override string toString() {
+ this.isWillSet() and
+ result = "willSet observer for " + assign.toString()
+ or
+ this.isDidSet() and
+ result = "didSet observer for " + assign.toString()
+ }
+
+ override Location getLocation() { result = assign.getLocation() }
+
+ AccessorDecl getObserver() { result = observer }
+
+ predicate isWillSet() { observer.isWillSet() }
+
+ predicate isDidSet() { observer.isDidSet() }
+
+ AssignExpr getAssignExpr() { result = assign }
+}
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll
index 446c1637101..4db8afaca7a 100644
--- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll
@@ -36,59 +36,73 @@ private import codeql.swift.controlflow.ControlFlowGraph
private import Completion
private import Scope
import ControlFlowGraphImplShared
+private import ControlFlowElements
+private import AstControlFlowTrees
module CfgScope {
abstract class Range_ extends AstNode {
- abstract predicate entry(AstNode first);
+ abstract predicate entry(ControlFlowElement first);
- abstract predicate exit(AstNode last, Completion c);
+ abstract predicate exit(ControlFlowElement last, Completion c);
}
private class BodyStmtCallableScope extends Range_ instanceof AbstractFunctionDecl {
- final override predicate entry(AstNode first) {
- super.getBody().(Stmts::BraceStmtTree).firstInner(first)
+ final override predicate entry(ControlFlowElement first) {
+ exists(Stmts::BraceStmtTree tree |
+ tree.getAst() = super.getBody() and
+ tree.firstInner(first)
+ )
}
- final override predicate exit(AstNode last, Completion c) {
- super.getBody().(Stmts::BraceStmtTree).last(last, c)
+ final override predicate exit(ControlFlowElement last, Completion c) {
+ exists(Stmts::BraceStmtTree tree |
+ tree.getAst() = super.getBody() and
+ tree.last(last, c)
+ )
}
}
}
/** Holds if `first` is first executed when entering `scope`. */
pragma[nomagic]
-predicate succEntry(CfgScope::Range_ scope, AstNode first) { scope.entry(first) }
+predicate succEntry(CfgScope::Range_ scope, ControlFlowElement first) { scope.entry(first) }
/** Holds if `last` with completion `c` can exit `scope`. */
pragma[nomagic]
-predicate succExit(CfgScope::Range_ scope, AstNode last, Completion c) { scope.exit(last, c) }
+predicate succExit(CfgScope::Range_ scope, ControlFlowElement last, Completion c) {
+ scope.exit(last, c)
+}
/**
* Control-flow for statements.
*/
module Stmts {
- class BraceStmtTree extends ControlFlowTree instanceof BraceStmt {
- override predicate propagatesAbnormal(AstNode node) { none() }
+ class BraceStmtTree extends AstControlFlowTree {
+ override BraceStmt ast;
- override predicate first(AstNode first) {
+ override predicate propagatesAbnormal(ControlFlowElement node) { none() }
+
+ override predicate first(ControlFlowElement first) {
this.firstInner(first)
or
- not exists(super.getFirstElement()) and first = this
+ not exists(ast.getFirstElement()) and first.asAstNode() = ast
}
- override predicate last(AstNode last, Completion c) {
+ override predicate last(ControlFlowElement last, Completion c) {
this.lastInner(last, c)
or
- not exists(super.getFirstElement()) and last = this and c instanceof SimpleCompletion
+ not exists(ast.getFirstElement()) and
+ last.asAstNode() = ast and
+ c instanceof SimpleCompletion
}
- predicate firstInner(AstNode first) { first(super.getFirstElement(), first) }
+ predicate firstInner(ControlFlowElement first) { astFirst(ast.getFirstElement(), first) }
/** Gets the body of the i'th `defer` statement. */
private BraceStmt getDeferStmtBody(int i) {
result =
rank[i](DeferStmt defer, int index |
- defer = super.getElement(index)
+ defer = ast.getElement(index)
|
defer.getBody() order by index
)
@@ -117,7 +131,7 @@ module Stmts {
int getDeferIndex(int i) {
exists(DeferStmt defer |
this.getDeferStmtBody(i) = defer.getBody() and
- super.getElement(result) = defer
+ ast.getElement(result) = defer
)
}
@@ -136,143 +150,153 @@ module Stmts {
)
}
- predicate lastInner(AstNode last, Completion c) {
+ predicate lastInner(ControlFlowElement last, Completion c) {
// Normal exit and no defer statements
- last(super.getLastElement(), last, c) and
+ astLast(ast.getLastElement(), last, c) and
not exists(this.getFirstDeferStmtBody()) and
c instanceof NormalCompletion
or
// Normal exit from the last defer statement to be executed
- last(this.getLastDeferStmtBody(), last, c) and
+ astLast(this.getLastDeferStmtBody(), last, c) and
c instanceof NormalCompletion
or
// Abnormal exit without any defer statements
not c instanceof NormalCompletion and
- last(super.getAnElement(), last, c) and
+ astLast(ast.getAnElement(), last, c) and
not exists(this.getFirstDeferStmtBody())
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// left-to-right evaluation of statements
exists(int i |
- last(super.getElement(i), pred, c) and
- first(super.getElement(i + 1), succ) and
+ astLast(ast.getElement(i), pred, c) and
+ astFirst(ast.getElement(i + 1), succ) and
c instanceof NormalCompletion
)
or
// Flow from last elements to the first defer statement to be executed
c instanceof NormalCompletion and
- last(super.getLastElement(), pred, c) and
- first(this.getFirstDeferStmtBody(), succ)
+ astLast(ast.getLastElement(), pred, c) and
+ astFirst(this.getFirstDeferStmtBody(), succ)
or
// Flow from a defer statement to the next defer to be executed
c instanceof NormalCompletion and
exists(int i |
- last(this.getDeferStmtBody(i), pred, c) and
- first(this.getDeferStmtBody(i - 1), succ)
+ astLast(this.getDeferStmtBody(i), pred, c) and
+ astFirst(this.getDeferStmtBody(i - 1), succ)
)
or
// Abnormal exit from an element to the first defer statement to be executed.
not c instanceof NormalCompletion and
exists(int i |
- last(super.getElement(i), pred, c) and
- first(this.getDeferStmtBodyAfterStmt(i), succ)
+ astLast(ast.getElement(i), pred, c) and
+ astFirst(this.getDeferStmtBodyAfterStmt(i), succ)
)
}
}
- private class ReturnStmtTree extends StandardPostOrderTree, ReturnStmt {
- final override ControlFlowTree getChildElement(int i) {
- result = this.getResult().getFullyConverted() and i = 0
+ private class ReturnStmtTree extends AstStandardPostOrderTree {
+ override ReturnStmt ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getResult().getFullyConverted() and i = 0
}
}
- private class FailTree extends LeafTree instanceof FailStmt { }
+ private class FailTree extends AstLeafTree {
+ override FailStmt ast;
+ }
- private class StmtConditionTree extends PostOrderTree instanceof StmtCondition {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getAnElement().getUnderlyingCondition()
+ private class StmtConditionTree extends AstPostOrderTree {
+ override StmtCondition ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getAnElement().getUnderlyingCondition()
}
- final override predicate first(AstNode first) {
- first(super.getFirstElement().getUnderlyingCondition().getFullyUnresolved(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getFirstElement().getUnderlyingCondition().getFullyUnresolved(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Left-to-right evaluation of elements
exists(int i |
- last(super.getElement(i).getUnderlyingCondition().getFullyUnresolved(), pred, c) and
+ astLast(ast.getElement(i).getUnderlyingCondition().getFullyUnresolved(), pred, c) and
c instanceof NormalCompletion and
- first(super.getElement(i + 1).getUnderlyingCondition().getFullyUnresolved(), succ)
+ astFirst(ast.getElement(i + 1).getUnderlyingCondition().getFullyUnresolved(), succ)
)
or
// Post-order: flow from thrown expression to the throw statement.
- last(super.getLastElement().getUnderlyingCondition().getFullyUnresolved(), pred, c) and
+ astLast(ast.getLastElement().getUnderlyingCondition().getFullyUnresolved(), pred, c) and
c instanceof NormalCompletion and
- succ = this
+ succ.asAstNode() = ast
}
}
- private class IfStmtTree extends PreOrderTree instanceof IfStmt {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getCondition().getFullyUnresolved() or
- child = super.getThen() or
- child = super.getElse()
+ private class IfStmtTree extends AstPreOrderTree {
+ override IfStmt ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getCondition().getFullyUnresolved() or
+ child.asAstNode() = ast.getThen() or
+ child.asAstNode() = ast.getElse()
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// Condition exits with a false completion and there is no `else` branch
- last(super.getCondition().getFullyUnresolved(), last, c) and
+ astLast(ast.getCondition().getFullyUnresolved(), last, c) and
c instanceof FalseCompletion and
- not exists(super.getElse())
+ not exists(ast.getElse())
or
// Then/Else branch exits with any completion
- last(super.getBranch(_), last, c)
+ astLast(ast.getBranch(_), last, c)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: flow from statement itself to first element of condition
- pred = this and
- first(super.getCondition().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getCondition().getFullyUnresolved(), succ) and
c instanceof SimpleCompletion
or
- last(super.getCondition().getFullyUnresolved(), pred, c) and
+ astLast(ast.getCondition().getFullyUnresolved(), pred, c) and
(
// Flow from last element of condition to first element of then branch
- c instanceof TrueCompletion and first(super.getThen(), succ)
+ c instanceof TrueCompletion and astFirst(ast.getThen(), succ)
or
// Flow from last element of condition to first element of else branch
- c instanceof FalseCompletion and first(super.getElse(), succ)
+ c instanceof FalseCompletion and astFirst(ast.getElse(), succ)
)
}
}
- private class GuardTree extends PreOrderTree instanceof GuardStmt {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getCondition().getFullyUnresolved() or
- child = super.getBody()
+ private class GuardTree extends AstPreOrderTree {
+ override GuardStmt ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getCondition().getFullyUnresolved() or
+ child.asAstNode() = ast.getBody()
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// Normal exit after evaluating the body
- last(super.getBody(), last, c) and
+ astLast(ast.getBody(), last, c) and
c instanceof NormalCompletion
or
// Exit when a condition is true
- last(super.getCondition().getFullyUnresolved(), last, c) and
+ astLast(ast.getCondition().getFullyUnresolved(), last, c) and
c instanceof TrueCompletion
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: flow from statement itself to first element of condition
- pred = this and
- first(super.getCondition().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getCondition().getFullyUnresolved(), succ) and
c instanceof SimpleCompletion
or
// Flow to the body when the condition is false
- last(super.getCondition().getFullyUnresolved(), pred, c) and
+ astLast(ast.getCondition().getFullyUnresolved(), pred, c) and
c instanceof FalseCompletion and
- first(super.getBody(), succ)
+ astFirst(ast.getBody(), succ)
}
}
@@ -284,14 +308,18 @@ module Stmts {
class LoopStmt = @for_each_stmt or ConditionalLoop;
- abstract class LoopTree extends PreOrderTree instanceof ConditionalLoop {
- abstract AstNode getCondition();
+ abstract class LoopTree extends AstPreOrderTree {
+ LoopTree() { ast instanceof ConditionalLoop }
- abstract AstNode getBody();
+ abstract ControlFlowElement getCondition();
- final override predicate propagatesAbnormal(AstNode child) { child = this.getCondition() }
+ abstract ControlFlowElement getBody();
- final override predicate last(AstNode last, Completion c) {
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child = this.getCondition()
+ }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
// Condition exits with a false completion
last(this.getCondition(), last, c) and
c instanceof FalseCompletion
@@ -300,190 +328,204 @@ module Stmts {
exists(BreakCompletion break |
last(this.getBody(), last, break) and
// Propagate the break upwards if we need to break out of multiple loops.
- if break.getTarget() = this then c instanceof SimpleCompletion else c = break
+ if break.getTarget() = ast then c instanceof SimpleCompletion else c = break
)
or
// Body exits with a completion that does not continue the loop
last(this.getBody(), last, c) and
not c instanceof BreakCompletion and
- not c.continuesLoop(this)
+ not c.continuesLoop(ast)
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
last(this.getCondition(), pred, c) and
c instanceof TrueCompletion and
first(this.getBody(), succ)
or
last(this.getBody(), pred, c) and
first(this.getCondition(), succ) and
- c.continuesLoop(this)
+ c.continuesLoop(ast)
}
}
- private class WhileTree extends LoopTree instanceof WhileStmt {
- final override AstNode getCondition() {
- result = WhileStmt.super.getCondition().getFullyUnresolved()
+ private class WhileTree extends LoopTree {
+ override WhileStmt ast;
+
+ final override ControlFlowElement getCondition() {
+ result.asAstNode() = ast.getCondition().getFullyUnresolved()
}
- final override AstNode getBody() { result = WhileStmt.super.getBody() }
+ final override ControlFlowElement getBody() { result.asAstNode() = ast.getBody() }
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
LoopTree.super.succ(pred, succ, c)
or
- pred = this and
+ pred.asAstNode() = ast and
first(this.getCondition(), succ) and
c instanceof SimpleCompletion
}
}
- private class RepeatWhileTree extends LoopTree instanceof RepeatWhileStmt {
- final override AstNode getCondition() {
- result = RepeatWhileStmt.super.getCondition().getFullyConverted()
+ private class RepeatWhileTree extends LoopTree {
+ override RepeatWhileStmt ast;
+
+ final override ControlFlowElement getCondition() {
+ result.asAstNode() = ast.getCondition().getFullyConverted()
}
- final override AstNode getBody() { result = RepeatWhileStmt.super.getBody() }
+ final override ControlFlowElement getBody() { result.asAstNode() = ast.getBody() }
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
LoopTree.super.succ(pred, succ, c)
or
// Pre-order: Flow from the element to the body.
- pred = this and
+ pred.asAstNode() = ast and
first(this.getBody(), succ) and
c instanceof SimpleCompletion
}
}
- private class ForEachTree extends ControlFlowTree instanceof ForEachStmt {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getSequence().getFullyConverted()
+ private class ForEachTree extends AstControlFlowTree {
+ override ForEachStmt ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getSequence().getFullyConverted()
or
- child = super.getPattern().getFullyUnresolved()
+ child.asAstNode() = ast.getPattern().getFullyUnresolved()
}
- final override predicate first(AstNode first) {
+ final override predicate first(ControlFlowElement first) {
// Unlike most other statements, `foreach` statements are not modelled in
// pre-order, because we use the `foreach` node itself to represent the
// emptiness test that determines whether to execute the loop body
- first(super.getSequence().getFullyConverted(), first)
+ astFirst(ast.getSequence().getFullyConverted(), first)
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// Emptiness test exits with no more elements
- last = this and
+ last.asAstNode() = ast and
c.(EmptinessCompletion).isEmpty()
or
// Body exits with a break completion
exists(BreakCompletion break |
- last(super.getBody(), last, break) and
+ astLast(ast.getBody(), last, break) and
// Propagate the break upwards if we need to break out of multiple loops.
- if break.getTarget() = this then c instanceof SimpleCompletion else c = break
+ if break.getTarget() = ast then c instanceof SimpleCompletion else c = break
)
or
// Body exits abnormally
- last(super.getBody(), last, c) and
+ astLast(ast.getBody(), last, c) and
not c instanceof NormalCompletion and
not c instanceof ContinueCompletion and
not c instanceof BreakCompletion
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Flow from last element of iterator expression to emptiness test
- last(super.getSequence().getFullyConverted(), pred, c) and
+ astLast(ast.getSequence().getFullyConverted(), pred, c) and
c instanceof NormalCompletion and
- succ = this
+ succ.asAstNode() = ast
or
// Flow from emptiness test to first element of variable declaration/loop body
- pred = this and
+ pred.asAstNode() = ast and
c = any(EmptinessCompletion ec | not ec.isEmpty()) and
- first(super.getPattern().getFullyUnresolved(), succ)
+ astFirst(ast.getPattern().getFullyUnresolved(), succ)
or
// Flow from last element of variable declaration ...
- last(super.getPattern().getFullyUnresolved(), pred, c) and
+ astLast(ast.getPattern().getFullyUnresolved(), pred, c) and
c instanceof SimpleCompletion and
(
// ... to first element of loop body if no 'where' clause exists,
- first(super.getBody(), succ) and
- not exists(super.getWhere())
+ astFirst(ast.getBody(), succ) and
+ not exists(ast.getWhere())
or
// ... or to the 'where' clause.
- first(super.getWhere().getFullyConverted(), succ)
+ astFirst(ast.getWhere().getFullyConverted(), succ)
)
or
// Flow from the where 'clause' ...
- last(super.getWhere().getFullyConverted(), pred, c) and
+ astLast(ast.getWhere().getFullyConverted(), pred, c) and
(
// to the loop body if the condition is true,
c instanceof TrueCompletion and
- first(super.getBody(), succ)
+ astFirst(ast.getBody(), succ)
or
// or to the emptiness test if the condition is false.
c instanceof FalseCompletion and
- succ = this
+ succ.asAstNode() = ast
)
or
// Flow from last element of loop body back to emptiness test.
- last(super.getBody(), pred, c) and
- c.continuesLoop(this) and
- succ = this
+ astLast(ast.getBody(), pred, c) and
+ c.continuesLoop(ast) and
+ succ.asAstNode() = ast
}
}
}
- private class BreakTree extends LeafTree instanceof BreakStmt { }
+ private class BreakTree extends AstLeafTree {
+ override BreakStmt ast;
+ }
- private class ContinueTree extends LeafTree instanceof ContinueStmt { }
+ private class ContinueTree extends AstLeafTree {
+ override ContinueStmt ast;
+ }
- private class SwitchTree extends PreOrderTree instanceof SwitchStmt {
- override predicate propagatesAbnormal(AstNode child) {
- child = super.getExpr().getFullyConverted()
+ private class SwitchTree extends AstPreOrderTree {
+ override SwitchStmt ast;
+
+ override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getExpr().getFullyConverted()
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// Switch expression exits normally and there are no cases
- not exists(super.getACase()) and
- last(super.getExpr().getFullyConverted(), last, c) and
+ not exists(ast.getACase()) and
+ astLast(ast.getExpr().getFullyConverted(), last, c) and
c instanceof NormalCompletion
or
// A statement exits (TODO: with a `break` completion?)
- last(super.getACase().getBody(), last, c) and
+ astLast(ast.getACase().getBody(), last, c) and
c instanceof NormalCompletion
// Note: There's no need for an exit with a non-match as
// Swift's switch statements are always exhaustive.
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Flow from last element of switch expression to first element of first case
c instanceof NormalCompletion and
- last(super.getExpr().getFullyConverted(), pred, c) and
- first(super.getFirstCase(), succ)
+ astLast(ast.getExpr().getFullyConverted(), pred, c) and
+ astFirst(ast.getFirstCase(), succ)
or
// Flow from last element of case pattern to next case
- exists(CaseStmt case, int i | case = super.getCase(i) |
- last(case.getLastLabel(), pred, c) and
+ exists(CaseStmt case, int i | case = ast.getCase(i) |
+ astLast(case.getLastLabel(), pred, c) and
c.(MatchingCompletion).isNonMatch() and
- first(super.getCase(i + 1), succ)
+ astFirst(ast.getCase(i + 1), succ)
)
or
// Flow from a case statement that ends in a fallthrough
// statement to the next statement
- last(super.getACase().getBody(), pred, c) and
- first(c.(FallthroughCompletion).getDestination().getBody(), succ)
+ astLast(ast.getACase().getBody(), pred, c) and
+ astFirst(c.(FallthroughCompletion).getDestination().getBody(), succ)
or
// Pre-order: flow from statement itself to first switch expression
- pred = this and
- first(super.getExpr().getFullyConverted(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getExpr().getFullyConverted(), succ) and
c instanceof SimpleCompletion
}
}
- private class CaseLabelItemTree extends PreOrderTree instanceof CaseLabelItem {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getGuard().getFullyConverted()
+ private class CaseLabelItemTree extends AstPreOrderTree {
+ override CaseLabelItem ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getGuard().getFullyConverted()
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// If the last node is the pattern ...
- last(super.getPattern().getFullyUnresolved(), last, c) and
+ astLast(ast.getPattern().getFullyUnresolved(), last, c) and
(
// then it's because we failed to match it
c.(MatchingCompletion).isNonMatch()
@@ -491,333 +533,466 @@ module Stmts {
// Or because, there is no guard (in which case we can also finish the evaluation
// here on a succesful match).
c.(MatchingCompletion).isMatch() and
- not super.hasGuard()
+ not ast.hasGuard()
)
or
// Or it can be the guard if a guard exists
exists(BooleanCompletion booleanComp |
- last(super.getGuard().getFullyUnresolved(), last, booleanComp)
+ astLast(ast.getGuard().getFullyUnresolved(), last, booleanComp)
|
booleanComp.getValue() = c.(MatchingCompletion).getValue()
)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: Flow from this to the pattern
- pred = this and
- first(super.getPattern().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getPattern().getFullyUnresolved(), succ) and
c instanceof SimpleCompletion
or
// Flow from a matching pattern to the guard, if any
- last(super.getPattern().getFullyUnresolved(), pred, c) and
+ astLast(ast.getPattern().getFullyUnresolved(), pred, c) and
c instanceof MatchingCompletion and
- succ = super.getGuard().getFullyConverted()
+ succ.asAstNode() = ast.getGuard().getFullyConverted()
}
}
- private class CaseTree extends PreOrderTree instanceof CaseStmt {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getALabel()
+ private class CaseTree extends AstPreOrderTree {
+ override CaseStmt ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getALabel()
or
- child = super.getBody()
+ child.asAstNode() = ast.getBody()
}
- final override predicate last(AstNode last, Completion c) {
+ final override predicate last(ControlFlowElement last, Completion c) {
// Case pattern exits with a non-match
- last(super.getLastLabel().getFullyUnresolved(), last, c) and
+ astLast(ast.getLastLabel().getFullyUnresolved(), last, c) and
not c.(MatchingCompletion).isMatch()
or
// Case body exits with any completion
- last(super.getBody(), last, c)
+ astLast(ast.getBody(), last, c)
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: Flow from the case statement itself to the first label
- pred = this and
- first(super.getFirstLabel().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getFirstLabel().getFullyUnresolved(), succ) and
c instanceof SimpleCompletion
or
// Left-to-right evaluation of labels until we find a match
exists(int i |
- last(super.getLabel(i).getFullyUnresolved(), pred, c) and
- first(super.getLabel(i + 1).getFullyUnresolved(), succ) and
+ astLast(ast.getLabel(i).getFullyUnresolved(), pred, c) and
+ astFirst(ast.getLabel(i + 1).getFullyUnresolved(), succ) and
c.(MatchingCompletion).isNonMatch()
)
or
// Flow from last element of pattern to first element of body
- last(super.getALabel().getFullyUnresolved(), pred, c) and
- first(super.getBody(), succ) and
+ astLast(ast.getALabel().getFullyUnresolved(), pred, c) and
+ astFirst(ast.getBody(), succ) and
c.(MatchingCompletion).isMatch()
}
}
- private class FallThroughTree extends LeafTree instanceof FallthroughStmt { }
+ private class FallThroughTree extends AstLeafTree {
+ override FallthroughStmt ast;
+ }
- private class DeferTree extends LeafTree instanceof DeferStmt { }
+ private class DeferTree extends AstLeafTree {
+ override DeferStmt ast;
+ }
- private class ThrowExprTree extends PostOrderTree instanceof ThrowStmt {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getSubExpr().getFullyConverted()
+ private class ThrowExprTree extends AstPostOrderTree {
+ override ThrowStmt ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getSubExpr().getFullyConverted()
}
- final override predicate first(AstNode first) {
- first(super.getSubExpr().getFullyConverted(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getSubExpr().getFullyConverted(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Post-order: flow from thrown expression to the throw statement.
- last(super.getSubExpr().getFullyConverted(), pred, c) and
+ astLast(ast.getSubExpr().getFullyConverted(), pred, c) and
c instanceof NormalCompletion and
- succ = this
+ succ.asAstNode() = ast
}
}
- class DoOrDoCatchStmt = @do_stmt or @do_catch_stmt;
+ abstract class DoOrDoCatchTree extends AstPreOrderTree {
+ DoOrDoCatchTree() {
+ ast instanceof DoStmt
+ or
+ ast instanceof DoCatchStmt
+ }
- abstract class DoOrDoCatchTree extends PreOrderTree instanceof DoOrDoCatchStmt {
- abstract AstNode getBody();
+ abstract ControlFlowElement getBody();
- override predicate last(AstNode last, Completion c) {
+ override predicate last(ControlFlowElement last, Completion c) {
// The last element of the body is always a candidate for the last element of the statement.
// Note that this is refined in `DoCatchTree` to only be the last statement if the body
// doesn't end with a throw completion.
last(this.getBody(), last, c)
}
- override predicate propagatesAbnormal(AstNode child) { none() }
+ override predicate propagatesAbnormal(ControlFlowElement child) { none() }
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: flow from statement itself to first element of body
- pred = this and
+ pred.asAstNode() = ast and
first(this.getBody(), succ) and
c instanceof SimpleCompletion
}
}
- class DoCatchTree extends DoOrDoCatchTree instanceof DoCatchStmt {
- final override AstNode getBody() { result = DoCatchStmt.super.getBody() }
+ class DoCatchTree extends DoOrDoCatchTree {
+ override DoCatchStmt ast;
- override predicate last(AstNode last, Completion c) {
+ final override ControlFlowTree getBody() { result.asAstNode() = ast.getBody() }
+
+ override predicate last(ControlFlowElement last, Completion c) {
DoOrDoCatchTree.super.last(last, c) and
not c instanceof ThrowCompletion
or
// Any catch can be the last element to be evaluated.
- last(super.getACatch(), last, c)
+ astLast(ast.getACatch().getBody(), last, c)
or
// We failed to match on any of the clauses.
// TODO: This can actually only happen if the enclosing function is marked with 'throws'.
// So we could make this more precise.
- last(super.getLastCatch(), last, c) and
+ astLast(ast.getLastCatch(), last, c) and
c = any(MatchingCompletion mc | not mc.isMatch())
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
DoOrDoCatchTree.super.succ(pred, succ, c)
or
// Flow from the body to the first catch when an exception occurs
last(this.getBody(), pred, c) and
c instanceof ThrowCompletion and
- first(super.getFirstCatch(), succ)
+ astFirst(ast.getFirstCatch(), succ)
or
exists(int i |
// Flow from one `catch` clause to the next
- last(super.getCatch(i), pred, c) and
- first(super.getCatch(i + 1), succ) and
+ astLast(ast.getCatch(i), pred, c) and
+ astFirst(ast.getCatch(i + 1), succ) and
c = any(MatchingCompletion mc | not mc.isMatch())
)
}
}
- class DoTree extends DoOrDoCatchTree instanceof DoStmt {
- final override AstNode getBody() { result = DoStmt.super.getBody() }
+ class DoTree extends DoOrDoCatchTree {
+ override DoStmt ast;
- final override predicate propagatesAbnormal(AstNode child) { child = this.getBody() }
+ final override ControlFlowElement getBody() { result.asAstNode() = ast.getBody() }
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getBody() }
}
}
/** A class that exists to allow control-flow through incorrectly extracted AST nodes. */
-private class UnknownAstTree extends LeafTree instanceof UnknownElement { }
+private class UnknownAstTree extends AstLeafTree {
+ UnknownAstTree() { ast.isUnknown() }
+}
/**
* Control-flow for patterns (which appear in `switch` statements
* and `catch` statements).
*/
module Patterns {
- private class TypedTree extends StandardPostOrderTree instanceof TypedPattern {
- final override ControlFlowTree getChildElement(int i) {
+ private class TypedTree extends AstStandardPostOrderTree {
+ override TypedPattern ast;
+
+ final override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = super.getSubPattern().getFullyUnresolved()
+ result.asAstNode() = ast.getSubPattern().getFullyUnresolved()
}
}
- private class TupleTree extends PreOrderTree instanceof TuplePattern {
- final override predicate propagatesAbnormal(AstNode n) {
- n = super.getAnElement().getFullyUnresolved()
+ private class TupleTree extends AstPreOrderTree {
+ override TuplePattern ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement n) {
+ n.asAstNode() = ast.getAnElement().getFullyUnresolved()
}
- final override predicate last(AstNode n, Completion c) {
+ final override predicate last(ControlFlowElement n, Completion c) {
// A subpattern failed to match
- last(super.getAnElement().getFullyUnresolved(), n, c) and
+ astLast(ast.getAnElement().getFullyUnresolved(), n, c) and
not c.(MatchingCompletion).isMatch()
or
// We finished matching on all subpatterns
- last(super.getLastElement().getFullyUnresolved(), n, c) and
+ astLast(ast.getLastElement().getFullyUnresolved(), n, c) and
c instanceof NormalCompletion
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: Flow from this to the first subpattern
- pred = this and
- first(super.getFirstElement().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getFirstElement().getFullyUnresolved(), succ) and
c instanceof SimpleCompletion
or
// Flow from an element that matched to the next element
exists(int i |
- last(super.getElement(i).getFullyUnresolved(), pred, c) and
+ astLast(ast.getElement(i).getFullyUnresolved(), pred, c) and
c.(MatchingCompletion).isMatch() and
- first(super.getElement(i + 1).getFullyUnresolved(), succ)
+ astFirst(ast.getElement(i + 1).getFullyUnresolved(), succ)
)
}
}
- private class ParenTree extends StandardPreOrderTree instanceof ParenPattern {
- final override ControlFlowTree getChildElement(int i) {
+ private class ParenTree extends AstStandardPreOrderTree {
+ override ParenPattern ast;
+
+ final override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = ParenPattern.super.getResolveStep()
+ result.asAstNode() = ast.getResolveStep()
}
}
- private class NamedTree extends LeafTree instanceof NamedPattern { }
+ private class NamedTree extends AstLeafTree {
+ override NamedPattern ast;
+ }
- private class BoolTree extends LeafTree instanceof BoolPattern { }
+ private class BoolTree extends AstLeafTree {
+ override BoolPattern ast;
+ }
- private class AnyTree extends LeafTree instanceof AnyPattern { }
+ private class AnyTree extends AstLeafTree {
+ override AnyPattern ast;
+ }
- private class IsTree extends StandardPostOrderTree instanceof IsPattern {
- final override ControlFlowTree getChildElement(int i) {
+ private class IsTree extends AstStandardPostOrderTree {
+ override IsPattern ast;
+
+ final override ControlFlowElement getChildElement(int i) {
// Note: `getSubPattern` only has a result if the `is` pattern is of the form `pattern as type`.
i = 0 and
- result = super.getSubPattern().getFullyUnresolved()
+ result.asAstNode() = ast.getSubPattern().getFullyUnresolved()
or
i = 1 and
- result = super.getCastTypeRepr()
+ result.asAstNode() = ast.getCastTypeRepr()
}
}
- private class EnumElementTree extends PreOrderTree instanceof EnumElementPattern {
- final override predicate propagatesAbnormal(AstNode n) {
- n = super.getSubPattern().getFullyUnresolved()
+ private class EnumElementTree extends AstPreOrderTree {
+ override EnumElementPattern ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement n) {
+ n.asAstNode() = ast.getSubPattern().getFullyUnresolved()
}
- final override predicate last(AstNode n, Completion c) {
+ final override predicate last(ControlFlowElement n, Completion c) {
// We finished the subpattern check
- last(super.getSubPattern().getFullyUnresolved(), n, c) and
+ astLast(ast.getSubPattern().getFullyUnresolved(), n, c) and
c instanceof NormalCompletion
or
// Or we got to the enum element check which failed
- n = this and
+ n.asAstNode() = ast and
c.(MatchingCompletion).isNonMatch()
or
// No sub pattern: We can either succeed or fail this match depending on the enum element check.
- n = this and
- not exists(super.getSubPattern()) and
+ n.asAstNode() = ast and
+ not exists(ast.getSubPattern()) and
c instanceof MatchingCompletion
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: Flow from the enumeration check to the subpattern
- pred = this and
- first(super.getSubPattern().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getSubPattern().getFullyUnresolved(), succ) and
c.(MatchingCompletion).isMatch()
}
}
- private class BindingTree extends PostOrderTree instanceof BindingPattern {
- final override predicate propagatesAbnormal(AstNode n) {
- n = super.getSubPattern().getFullyUnresolved()
+ private class BindingTree extends AstPostOrderTree {
+ override BindingPattern ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement n) {
+ n.asAstNode() = ast.getSubPattern().getFullyUnresolved()
}
- final override predicate first(AstNode n) {
- first(super.getSubPattern().getFullyUnresolved(), n)
+ final override predicate first(ControlFlowElement n) {
+ astFirst(ast.getSubPattern().getFullyUnresolved(), n)
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
- last(super.getSubPattern().getFullyUnresolved(), pred, c) and
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getSubPattern().getFullyUnresolved(), pred, c) and
c.(MatchingCompletion).isMatch() and
- succ = this
+ succ.asAstNode() = ast
}
}
- private class ExprTree extends StandardPostOrderTree instanceof ExprPattern {
- final override ControlFlowTree getChildElement(int i) {
+ private class ExprTree extends AstStandardPostOrderTree {
+ override ExprPattern ast;
+
+ final override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = super.getSubExpr().getFullyConverted()
+ result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
- private class OptionalSomeTree extends PreOrderTree instanceof OptionalSomePattern {
- final override predicate propagatesAbnormal(AstNode n) {
- n = super.getSubPattern().getFullyUnresolved()
+ private class OptionalSomeTree extends AstPreOrderTree {
+ override OptionalSomePattern ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement n) {
+ n.asAstNode() = ast.getSubPattern().getFullyUnresolved()
}
- final override predicate last(AstNode n, Completion c) {
+ final override predicate last(ControlFlowElement n, Completion c) {
// The subpattern check either failed or succeeded
- last(super.getSubPattern().getFullyUnresolved(), n, c) and
+ astLast(ast.getSubPattern().getFullyUnresolved(), n, c) and
c instanceof NormalCompletion
or
// Or we got to the some/none check and it failed
- n = this and
+ n.asAstNode() = ast and
not c.(MatchingCompletion).isMatch()
}
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre-order: Flow from a matching some/none check to the subpattern
- pred = this and
- first(super.getSubPattern().getFullyUnresolved(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getSubPattern().getFullyUnresolved(), succ) and
c.(MatchingCompletion).isMatch()
}
}
}
module Decls {
- private class VarDeclTree extends LeafTree instanceof VarDecl { }
+ private class VarDeclTree extends AstLeafTree {
+ override VarDecl ast;
+ }
- private class PatternBindingDeclTree extends StandardPostOrderTree instanceof PatternBindingDecl {
- final override ControlFlowTree getChildElement(int i) {
+ private class PatternBindingDeclTree extends AstStandardPostOrderTree {
+ override PatternBindingDecl ast;
+
+ final override ControlFlowElement getChildElement(int i) {
exists(int j |
i = 2 * j and
- result = super.getPattern(j).getFullyUnresolved()
+ result.asAstNode() = ast.getPattern(j).getFullyUnresolved()
)
or
exists(int j |
i = 2 * j + 1 and
- result = super.getInit(j).getFullyConverted()
+ result.asAstNode() = ast.getInit(j).getFullyConverted()
)
}
}
}
module Exprs {
- private class AssignExprTree extends StandardPostOrderTree instanceof AssignExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getDest().getFullyConverted() and i = 0
- or
- result = super.getSource().getFullyConverted() and i = 1
+ module AssignExprs {
+ /**
+ * The control-flow of an assignment operation.
+ *
+ * There are two implementation of this base class:
+ * - One where the left-hand side has direct-to-storage-access semantics
+ * - One where the left-hand side has direct-to-implementation-access semantics
+ */
+ abstract private class AssignExprTree extends AstControlFlowTree {
+ override AssignExpr ast;
+
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getDest().getFullyConverted(), first)
+ }
+
+ abstract predicate isSet(ControlFlowElement n);
+
+ abstract predicate isLast(ControlFlowElement n, Completion c);
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getDest().getFullyConverted() or
+ child.asAstNode() = ast.getSource().getFullyConverted()
+ }
+
+ predicate hasWillSetObserver() { isPropertyObserverElement(_, any(WillSetObserver obs), ast) }
+
+ predicate hasDidSetObserver() { isPropertyObserverElement(_, any(DidSetObserver obs), ast) }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ isPropertyObserverElement(last, any(DidSetObserver obs), ast) and
+ completionIsValidFor(c, last)
+ or
+ not this.hasDidSetObserver() and
+ this.isLast(last, c)
+ }
+
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ // Flow from the destination to the source
+ astLast(ast.getDest().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ astFirst(ast.getSource().getFullyConverted(), succ)
+ or
+ // Flow from the source to the `willSet` observer, if any. Otherwise, flow to the set operation
+ astLast(ast.getSource().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ (
+ if this.hasWillSetObserver()
+ then isPropertyObserverElement(succ, any(WillSetObserver obs), ast)
+ else this.isSet(succ)
+ )
+ or
+ // Flow from the set operation to the `didSet` observer, if any
+ this.isSet(pred) and
+ completionIsValidFor(c, pred) and
+ isPropertyObserverElement(succ, any(DidSetObserver obs), ast)
+ }
+ }
+
+ /**
+ * The control-flow for assignments where the left-hand side has
+ * direct-to-implmentation-access semantics.
+ */
+ class PropertyAssignExpr extends AssignExprTree {
+ AccessorDecl accessorDecl;
+
+ PropertyAssignExpr() { isPropertySetterElement(_, accessorDecl, ast) }
+
+ final override predicate isLast(ControlFlowElement last, Completion c) {
+ isPropertySetterElement(last, accessorDecl, ast) and
+ completionIsValidFor(c, last)
+ }
+
+ final override predicate isSet(ControlFlowElement node) {
+ isPropertySetterElement(node, _, ast)
+ }
+ }
+
+ /**
+ * The control-flow for assignments where the left-hand side has
+ * direct-to-storage-access semantics.
+ */
+ class DirectAssignExpr extends AssignExprTree {
+ DirectAssignExpr() { not this instanceof PropertyAssignExpr }
+
+ final override predicate isLast(ControlFlowElement last, Completion c) {
+ last.asAstNode() = ast and
+ completionIsValidFor(c, last)
+ }
+
+ final override predicate isSet(ControlFlowElement node) { node.asAstNode() = ast }
}
}
- private class BindOptionalTree extends StandardPostOrderTree instanceof BindOptionalExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class BindOptionalTree extends AstStandardPostOrderTree {
+ override BindOptionalExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
- private class CaptureListTree extends StandardPostOrderTree instanceof CaptureListExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getBindingDecl(i).getFullyUnresolved()
+ private class CaptureListTree extends AstStandardPostOrderTree {
+ override CaptureListExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getBindingDecl(i).getFullyUnresolved()
or
- i = super.getNumberOfBindingDecls() and
- result = super.getClosureBody().getFullyConverted()
+ i = ast.getNumberOfBindingDecls() and
+ result.asAstNode() = ast.getClosureBody().getFullyConverted()
}
}
@@ -825,7 +1000,9 @@ module Exprs {
class Closure = @auto_closure_expr or @closure_expr;
// TODO: Traverse the expressions in the capture list once we extract it.
- private class ClosureTree extends LeafTree instanceof ClosureExpr { }
+ private class ClosureTree extends AstLeafTree {
+ override ClosureExpr ast;
+ }
/**
* An autoclosure expression that is generated as part of a logical operation.
@@ -837,298 +1014,532 @@ module Exprs {
* So the `true` edge from `b1` cannot just go to `b2` since this is an implicit autoclosure.
* To handle this dig into the autoclosure when it's an operand of a logical operator.
*/
- private class LogicalAutoClosureTree extends PreOrderTree instanceof AutoClosureExpr {
- LogicalAutoClosureTree() { this = any(LogicalOperation op).getAnOperand() }
+ private class LogicalAutoClosureTree extends AstPreOrderTree {
+ override AutoClosureExpr ast;
- override predicate last(AstNode last, Completion c) {
- exists(Completion completion | last(super.getReturn(), last, completion) |
+ LogicalAutoClosureTree() { ast = any(LogicalOperation op).getAnOperand() }
+
+ override predicate last(ControlFlowElement last, Completion c) {
+ exists(Completion completion | astLast(ast.getReturn(), last, completion) |
if completion instanceof ReturnCompletion
then c instanceof SimpleCompletion
else c = completion
)
}
- override predicate propagatesAbnormal(AstNode child) { child = super.getReturn() }
+ override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getReturn()
+ }
- override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
// Pre order: Flow from this to the uniquely wrapped expr
- pred = this and
- first(super.getReturn(), succ) and
+ pred.asAstNode() = ast and
+ astFirst(ast.getReturn(), succ) and
c instanceof SimpleCompletion
}
}
/** An autoclosure expression that is _not_ part of a logical operation. */
- private class AutoClosureTree extends LeafTree instanceof AutoClosureExpr {
+ private class AutoClosureTree extends AstLeafTree {
+ override AutoClosureExpr ast;
+
AutoClosureTree() { not this instanceof LogicalAutoClosureTree }
}
}
- private class InOutTree extends StandardPostOrderTree instanceof InOutExpr {
- final override ControlFlowTree getChildElement(int i) {
- i = 0 and result = super.getSubExpr().getFullyConverted()
+ private class InOutTree extends AstStandardPostOrderTree {
+ override InOutExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ i = 0 and result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
- private class SubScriptTree extends StandardPostOrderTree instanceof SubscriptExpr {
- final override ControlFlowTree getChildElement(int i) {
- i = 0 and result = super.getBaseExpr().getFullyConverted()
+ private class SubscriptTree extends AstControlFlowTree {
+ override SubscriptExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getBaseExpr().getFullyConverted()
or
- i = 1 and result = super.getAnArgument().getExpr().getFullyConverted()
+ child.asAstNode() = ast.getAnArgument().getExpr().getFullyConverted()
}
- }
- private class TupleTree extends StandardPostOrderTree instanceof TupleExpr {
- TupleTree() { not this.getAnElement() = any(LogicalOperation op).getAnOperand() }
-
- final override ControlFlowTree getChildElement(int i) {
- result = super.getElement(i).getFullyConverted()
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getBaseExpr().getFullyConverted(), first)
}
- }
- private class TupleElementTree extends StandardPostOrderTree instanceof TupleElementExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ final override predicate last(ControlFlowElement last, Completion c) {
+ (
+ // If we need to do a call to a getter/setter, in which case
+ // the index expression is the last expression we compute before we call the property access.
+ if ignoreAstElement(ast)
+ then isPropertyGetterElement(last, _, ast)
+ else
+ // If the subscript has direct-to-storage semantics we transfer flow to th subscript
+ // expression itself.
+ last.asAstNode() = ast
+ ) and
+ completionIsValidFor(c, last)
}
- }
- private class RebindSelfInConstructorTree extends StandardPostOrderTree instanceof RebindSelfInConstructorExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
- }
- }
-
- private class SuperRefTree extends LeafTree instanceof SuperRefExpr { }
-
- private class DotSyntaxBaseIgnoredTree extends StandardPostOrderTree instanceof DotSyntaxBaseIgnoredExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getQualifier().getFullyConverted() and i = 0
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ astFirst(ast.getFirstArgument().getExpr().getFullyConverted(), succ)
or
- result = super.getSubExpr().getFullyConverted() and i = 1
+ exists(int i |
+ astLast(ast.getArgument(i).getExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ astFirst(ast.getArgument(i + 1).getExpr().getFullyConverted(), succ)
+ )
+ or
+ astLast(ast.getLastArgument().getExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ (
+ if ignoreAstElement(ast)
+ then isPropertyGetterElement(succ, _, ast)
+ else succ.asAstNode() = ast
+ )
}
}
- private class TypeTree extends LeafTree instanceof TypeExpr { }
+ private class TupleTree extends AstStandardPostOrderTree {
+ override TupleExpr ast;
- private class DynamicTypeTree extends StandardPostOrderTree instanceof DynamicTypeExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getBaseExpr().getFullyConverted() and i = 0
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getElement(i).getFullyConverted()
}
}
- private class LazyInitializerTree extends StandardPostOrderTree instanceof LazyInitializerExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class TupleElementTree extends AstStandardPostOrderTree {
+ override TupleElementExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
- private class ObjCSelectorTree extends StandardPostOrderTree instanceof ObjCSelectorExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class RebindSelfInConstructorTree extends AstStandardPostOrderTree {
+ override RebindSelfInConstructorExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
- private class OneWayTree extends StandardPostOrderTree instanceof OneWayExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class SuperRefTree extends AstLeafTree {
+ override SuperRefExpr ast;
+ }
+
+ private class DotSyntaxBaseIgnoredTree extends AstStandardPostOrderTree {
+ override DotSyntaxBaseIgnoredExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getQualifier().getFullyConverted() and i = 0
+ or
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 1
}
}
- private class OptionalEvaluationTree extends StandardPostOrderTree instanceof OptionalEvaluationExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class TypeTree extends AstLeafTree {
+ override TypeExpr ast;
+ }
+
+ private class DynamicTypeTree extends AstStandardPostOrderTree {
+ override DynamicTypeExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getBaseExpr().getFullyConverted() and i = 0
}
}
- private class NonInterpolatedLiteralExprTree extends LeafTree instanceof LiteralExpr {
+ private class LazyInitializerTree extends AstStandardPostOrderTree {
+ override LazyInitializerExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
+ }
+ }
+
+ private class ObjCSelectorTree extends AstStandardPostOrderTree {
+ override ObjCSelectorExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
+ }
+ }
+
+ private class OneWayTree extends AstStandardPostOrderTree {
+ override OneWayExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
+ }
+ }
+
+ private class OptionalEvaluationTree extends AstStandardPostOrderTree {
+ override OptionalEvaluationExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
+ }
+ }
+
+ private class NonInterpolatedLiteralExprTree extends AstLeafTree {
+ override LiteralExpr ast;
+
NonInterpolatedLiteralExprTree() {
// This one needs special handling
- not this instanceof InterpolatedStringLiteralExpr
+ not ast instanceof InterpolatedStringLiteralExpr
}
}
- private class InterpolatedStringLiteralExprTree extends StandardPostOrderTree instanceof InterpolatedStringLiteralExpr {
- final override ControlFlowTree getChildElement(int i) {
+ private class InterpolatedStringLiteralExprTree extends AstStandardPostOrderTree {
+ override InterpolatedStringLiteralExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
none() // TODO
}
}
- private class DeclRefExprTree extends LeafTree instanceof DeclRefExpr { }
+ module DeclRefExprs {
+ class DeclRefExprLValueTree extends AstLeafTree {
+ override DeclRefExpr ast;
- private class MemberRefTree extends StandardPostOrderTree instanceof MemberRefExpr {
- final override AstNode getChildElement(int i) {
- result = super.getBaseExpr().getFullyConverted() and i = 0
+ DeclRefExprLValueTree() { isLValue(ast) }
+ }
+
+ abstract class DeclRefExprRValueTree extends AstControlFlowTree {
+ override DeclRefExpr ast;
+
+ DeclRefExprRValueTree() { isRValue(ast) }
+
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ none()
+ }
+
+ override predicate propagatesAbnormal(ControlFlowElement child) { none() }
+ }
+
+ private class PropertyDeclRefRValueTree extends DeclRefExprRValueTree {
+ AccessorDecl accessor;
+
+ PropertyDeclRefRValueTree() { isPropertyGetterElement(_, accessor, ast) }
+
+ final override predicate first(ControlFlowElement first) {
+ isPropertyGetterElement(first, accessor, ast)
+ }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ isPropertyGetterElement(last, accessor, ast) and
+ completionIsValidFor(c, last)
+ }
+ }
+
+ private class DirectDeclRefRValueTree extends DeclRefExprRValueTree {
+ DirectDeclRefRValueTree() { not this instanceof PropertyDeclRefRValueTree }
+
+ final override predicate first(ControlFlowElement first) { first.asAstNode() = ast }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ last.asAstNode() = ast and
+ completionIsValidFor(c, last)
+ }
}
}
- private class ApplyExprTree extends StandardPostOrderTree instanceof ApplyExpr {
+ module MemberRefs {
+ /**
+ * The control-flow of a member reference expression.
+ *
+ * There are two implementation of this base class:
+ * - One for lvalues
+ * - One for rvalues
+ */
+ abstract private class MemberRefTreeBase extends AstControlFlowTree {
+ override MemberRefExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getBaseExpr().getFullyConverted()
+ }
+
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getBaseExpr().getFullyConverted(), first)
+ }
+ }
+
+ /**
+ * The lvalue implementation of `MemberRefTreeBase`
+ */
+ private class MemberRefLValueTree extends MemberRefTreeBase {
+ MemberRefLValueTree() { isLValue(ast) }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ last.asAstNode() = ast and
+ completionIsValidFor(c, last)
+ }
+
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ succ.asAstNode() = ast
+ }
+ }
+
+ /**
+ * The rvalue base implementation of `MemberRefTreeBase`.
+ *
+ * There are two implementations of this class:
+ * - One for direct-storage semantics
+ * - One for calls to getters
+ */
+ abstract private class MemberRefRValueTree extends MemberRefTreeBase {
+ MemberRefRValueTree() { isRValue(ast) }
+ }
+
+ /**
+ * Control-flow for rvalue member accesses with direct-to-storage semantics
+ * or ordinary semantics without a getter.
+ */
+ private class DirectMemberRefRValue extends MemberRefRValueTree {
+ DirectMemberRefRValue() { not this instanceof PropertyMemberRefRValue }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ last.asAstNode() = ast and
+ completionIsValidFor(c, last)
+ }
+
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ succ.asAstNode() = ast
+ }
+ }
+
+ /**
+ * Control-flow for rvalue member accesses with direct-to-implementation semantics
+ * or ordinary semantics that includes a getter.
+ */
+ private class PropertyMemberRefRValue extends MemberRefRValueTree {
+ AccessorDecl accessor;
+
+ PropertyMemberRefRValue() { isPropertyGetterElement(_, accessor, ast) }
+
+ final override predicate last(ControlFlowElement last, Completion c) {
+ isPropertyGetterElement(last, accessor, ast) and
+ completionIsValidFor(c, last)
+ }
+
+ override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getBaseExpr().getFullyConverted(), pred, c) and
+ c instanceof NormalCompletion and
+ isPropertyGetterElement(succ, accessor, ast)
+ }
+ }
+ }
+
+ private class ApplyExprTree extends AstStandardPostOrderTree {
+ override ApplyExpr ast;
+
ApplyExprTree() {
// This one is handled in `LogicalNotTree`.
- not this instanceof UnaryLogicalOperation and
+ not ast instanceof UnaryLogicalOperation and
// These are handled in `LogicalOrTree` and `LogicalAndTree`.
- not this instanceof BinaryLogicalOperation
+ not ast instanceof BinaryLogicalOperation
}
- final override ControlFlowTree getChildElement(int i) {
+ final override ControlFlowElement getChildElement(int i) {
i = -1 and
- result = super.getFunction().getFullyConverted()
+ result.asAstNode() = ast.getFunction().getFullyConverted()
or
- result = super.getArgument(i).getExpr().getFullyConverted()
+ result.asAstNode() = ast.getArgument(i).getExpr().getFullyConverted()
}
}
- private class DefaultArgumentTree extends LeafTree instanceof DefaultArgumentExpr { }
+ private class DefaultArgumentTree extends AstLeafTree {
+ override DefaultArgumentExpr ast;
+ }
- private class ForceValueTree extends StandardPostOrderTree instanceof ForceValueExpr {
- override AstNode getChildElement(int i) {
+ private class ForceValueTree extends AstStandardPostOrderTree {
+ override ForceValueExpr ast;
+
+ override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = super.getSubExpr().getFullyConverted()
+ result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
- private class LogicalAndTree extends PostOrderTree, LogicalAndExpr {
- final override predicate propagatesAbnormal(AstNode child) {
- child = this.getAnOperand().getFullyConverted()
+ private class LogicalAndTree extends AstPostOrderTree {
+ override LogicalAndExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getAnOperand().getFullyConverted()
}
- final override predicate first(AstNode first) {
- first(this.getLeftOperand().getFullyConverted(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getLeftOperand().getFullyConverted(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
- last(this.getLeftOperand().getFullyConverted(), pred, c) and
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getLeftOperand().getFullyConverted(), pred, c) and
c instanceof TrueCompletion and
- first(this.getRightOperand().getFullyConverted(), succ)
+ astFirst(ast.getRightOperand().getFullyConverted(), succ)
or
- last(this.getLeftOperand().getFullyConverted(), pred, c) and
+ astLast(ast.getLeftOperand().getFullyConverted(), pred, c) and
c instanceof FalseCompletion and
- succ = this
+ succ.asAstNode() = ast
or
- last(this.getRightOperand().getFullyConverted(), pred, c) and
+ astLast(ast.getRightOperand().getFullyConverted(), pred, c) and
c instanceof NormalCompletion and
- succ = this
+ succ.asAstNode() = ast
}
}
- private class LogicalNotTree extends PostOrderTree, NotExpr {
- final override predicate propagatesAbnormal(AstNode child) {
- child = this.getOperand().getFullyConverted()
+ private class LogicalNotTree extends AstPostOrderTree {
+ override NotExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getOperand().getFullyConverted()
}
- final override predicate first(AstNode first) {
- first(this.getOperand().getFullyConverted(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getOperand().getFullyConverted(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
- succ = this and
- last(this.getOperand().getFullyConverted(), pred, c) and
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ succ.asAstNode() = ast and
+ astLast(ast.getOperand().getFullyConverted(), pred, c) and
c instanceof NormalCompletion
}
}
- private class LogicalOrTree extends PostOrderTree, LogicalOrExpr {
- final override predicate propagatesAbnormal(AstNode child) {
- child = this.getAnOperand().getFullyConverted()
+ private class LogicalOrTree extends AstPostOrderTree {
+ override LogicalOrExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getAnOperand().getFullyConverted()
}
- final override predicate first(AstNode first) {
- first(this.getLeftOperand().getFullyConverted(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getLeftOperand().getFullyConverted(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
- last(this.getLeftOperand().getFullyConverted(), pred, c) and
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getLeftOperand().getFullyConverted(), pred, c) and
c instanceof FalseCompletion and
- first(this.getRightOperand().getFullyConverted(), succ)
+ astFirst(ast.getRightOperand().getFullyConverted(), succ)
or
- last(this.getLeftOperand().getFullyConverted(), pred, c) and
+ astLast(ast.getLeftOperand().getFullyConverted(), pred, c) and
c instanceof TrueCompletion and
- succ = this
+ succ.asAstNode() = ast
or
- last(this.getRightOperand().getFullyConverted(), pred, c) and
+ astLast(ast.getRightOperand().getFullyConverted(), pred, c) and
c instanceof NormalCompletion and
- succ = this
+ succ.asAstNode() = ast
}
}
- private class VarargExpansionTree extends StandardPostOrderTree instanceof VarargExpansionExpr {
- final override ControlFlowTree getChildElement(int i) {
+ private class VarargExpansionTree extends AstStandardPostOrderTree {
+ override VarargExpansionExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = super.getSubExpr().getFullyConverted()
+ result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
- private class ArrayTree extends StandardPostOrderTree instanceof ArrayExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getElement(i).getFullyConverted()
+ private class ArrayTree extends AstStandardPostOrderTree {
+ override ArrayExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getElement(i).getFullyConverted()
}
}
- private class EnumIsCaseTree extends StandardPostOrderTree instanceof EnumIsCaseExpr {
- final override ControlFlowTree getChildElement(int i) {
- result = super.getSubExpr().getFullyConverted() and i = 0
+ private class EnumIsCaseTree extends AstStandardPostOrderTree {
+ override EnumIsCaseExpr ast;
+
+ final override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
or
- result = super.getTypeRepr().getFullyUnresolved() and i = 1
+ result.asAstNode() = ast.getTypeRepr().getFullyUnresolved() and i = 1
}
}
- private class IfTree extends PostOrderTree instanceof IfExpr {
- final override predicate propagatesAbnormal(AstNode child) {
- child = super.getCondition().getFullyConverted()
+ private class IfTree extends AstPostOrderTree {
+ override IfExpr ast;
+
+ final override predicate propagatesAbnormal(ControlFlowElement child) {
+ child.asAstNode() = ast.getCondition().getFullyConverted()
or
- child = super.getBranch(_).getFullyConverted()
+ child.asAstNode() = ast.getBranch(_).getFullyConverted()
}
- final override predicate first(AstNode first) {
- first(super.getCondition().getFullyConverted(), first)
+ final override predicate first(ControlFlowElement first) {
+ astFirst(ast.getCondition().getFullyConverted(), first)
}
- final override predicate succ(AstNode pred, AstNode succ, Completion c) {
- last(super.getCondition().getFullyConverted(), pred, c) and
+ final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ astLast(ast.getCondition().getFullyConverted(), pred, c) and
exists(boolean b |
b = c.(BooleanCompletion).getValue() and
- first(super.getBranch(b).getFullyConverted(), succ)
+ astFirst(ast.getBranch(b).getFullyConverted(), succ)
)
or
- last(super.getBranch(_).getFullyConverted(), pred, c) and
- succ = this and
+ astLast(ast.getBranch(_).getFullyConverted(), pred, c) and
+ succ.asAstNode() = ast and
c instanceof NormalCompletion
}
}
- private class TryTree extends StandardPostOrderTree instanceof TryExpr {
- override ControlFlowTree getChildElement(int i) {
+ private class TryTree extends AstStandardPostOrderTree {
+ override TryExpr ast;
+
+ override ControlFlowElement getChildElement(int i) {
i = 0 and
- result = super.getSubExpr().getFullyConverted()
+ result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
- private class DictionaryLiteralTree extends StandardPostOrderTree instanceof DictionaryExpr {
- override ControlFlowTree getChildElement(int i) { result = super.getElement(i) }
+ private class DictionaryLiteralTree extends AstStandardPostOrderTree {
+ override DictionaryExpr ast;
+
+ override ControlFlowElement getChildElement(int i) {
+ result.asAstNode() = ast.getElement(i).getFullyConverted()
+ }
}
module Conversions {
class ConversionOrIdentity = @identity_expr or @explicit_cast_expr or @implicit_conversion_expr;
- abstract class ConversionOrIdentityTree extends StandardPostOrderTree instanceof ConversionOrIdentity {
+ abstract class ConversionOrIdentityTree extends AstStandardPostOrderTree {
+ ConversionOrIdentityTree() { ast instanceof ConversionOrIdentity }
+
abstract predicate convertsFrom(Expr e);
- override ControlFlowTree getChildElement(int i) {
+ override ControlFlowElement getChildElement(int i) {
i = 0 and
- this.convertsFrom(result)
+ this.convertsFrom(result.asAstNode())
}
}
// This isn't actually a conversion, but it behaves like one.
- private class IdentityTree extends ConversionOrIdentityTree instanceof IdentityExpr {
- override predicate convertsFrom(Expr e) { IdentityExpr.super.convertsFrom(e) }
+ private class IdentityTree extends ConversionOrIdentityTree {
+ override IdentityExpr ast;
+
+ override predicate convertsFrom(Expr e) { ast.convertsFrom(e) }
}
- private class ExplicitCastTree extends ConversionOrIdentityTree instanceof ExplicitCastExpr {
- override predicate convertsFrom(Expr e) { ExplicitCastExpr.super.convertsFrom(e) }
+ private class ExplicitCastTree extends ConversionOrIdentityTree {
+ override ExplicitCastExpr ast;
+
+ override predicate convertsFrom(Expr e) { ast.convertsFrom(e) }
}
- private class ImplicitConversionTree extends ConversionOrIdentityTree instanceof ImplicitConversionExpr {
- override predicate convertsFrom(Expr e) { ImplicitConversionExpr.super.convertsFrom(e) }
+ private class ImplicitConversionTree extends ConversionOrIdentityTree {
+ override ImplicitConversionExpr ast;
+
+ override predicate convertsFrom(Expr e) { ast.convertsFrom(e) }
}
}
}
@@ -1140,8 +1551,8 @@ private Scope parent(Scope n) {
/** Gets the CFG scope of node `n`. */
pragma[inline]
-CfgScope getCfgScope(AstNode n) {
- exists(AstNode n0 |
+CfgScope getCfgScope(ControlFlowElement n) {
+ exists(ControlFlowElement n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = getCfgScopeImpl(n0)
)
@@ -1151,11 +1562,18 @@ cached
private module Cached {
/** Gets the CFG scope of node `n`. */
cached
- CfgScope getCfgScopeImpl(AstNode n) {
+ CfgScope getCfgScopeImpl(ControlFlowElement n) {
forceCachingInSameStage() and
result = parent*(scopeOf(n))
}
+ private CfgScope scopeOf(ControlFlowElement n) {
+ result = scopeOfAst(n.asAstNode()) or
+ result = scopeOfAst(n.(PropertyGetterElement).getRef()) or
+ result = scopeOfAst(n.(PropertySetterElement).getAssignExpr()) or
+ result = scopeOfAst(n.(PropertyObserverElement).getAssignExpr())
+ }
+
cached
newtype TSuccessorType =
TSuccessorSuccessor() or
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplSpecific.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplSpecific.qll
index ff72929e41d..7c11c2c2f84 100644
--- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplSpecific.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplSpecific.qll
@@ -1,30 +1,14 @@
private import swift as S
private import ControlFlowGraphImpl as Impl
-private import Completion as Comp
+import Completion
private import codeql.swift.controlflow.ControlFlowGraph as CFG
private import Splitting as Splitting
+private import Scope
+import ControlFlowElements
+import AstControlFlowTrees
/** The base class for `ControlFlowTree`. */
-class ControlFlowTreeBase extends S::AstNode { }
-
-class ControlFlowElement = S::AstNode;
-
-class Completion = Comp::Completion;
-
-/**
- * Hold if `c` represents normal evaluation of a statement or an
- * expression.
- */
-predicate completionIsNormal(Completion c) { c instanceof Comp::NormalCompletion }
-
-/**
- * Hold if `c` represents simple (normal) evaluation of a statement or an
- * expression.
- */
-predicate completionIsSimple(Completion c) { c instanceof Comp::SimpleCompletion }
-
-/** Holds if `c` is a valid completion for `e`. */
-predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) }
+class ControlFlowTreeBase = ControlFlowElement;
class CfgScope = CFG::CfgScope;
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll
index 99dc955d1e6..c06c67d1665 100644
--- a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll
@@ -16,7 +16,7 @@ private module Scope {
class TypeRange = Callable::TypeRange;
class Range extends AstNode, TypeRange {
- Range getOuterScope() { result = scopeOf(this) }
+ Range getOuterScope() { result = scopeOfAst(this) }
}
}
@@ -235,14 +235,14 @@ private module Cached {
}
cached
- AstNode getParent(AstNode ast) { getChild(result, _) = ast }
+ AstNode getParentOfAst(AstNode ast) { getChild(result, _) = ast }
}
/** Gets the enclosing scope of a node */
cached
-AstNode scopeOf(AstNode n) {
- exists(AstNode p | p = getParent(n) |
- if p instanceof Scope then p = result else result = scopeOf(p)
+AstNode scopeOfAst(AstNode n) {
+ exists(AstNode p | p = getParentOfAst(n) |
+ if p instanceof Scope then p = result else result = scopeOfAst(p)
)
}
diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Splitting.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Splitting.qll
index d09e9b2fd2b..e0b2961283b 100644
--- a/swift/ql/lib/codeql/swift/controlflow/internal/Splitting.qll
+++ b/swift/ql/lib/codeql/swift/controlflow/internal/Splitting.qll
@@ -6,6 +6,8 @@ private import swift
private import Completion
private import ControlFlowGraphImpl
private import codeql.swift.controlflow.ControlFlowGraph
+private import AstControlFlowTrees
+private import ControlFlowElements
cached
private module Cached {
@@ -37,7 +39,7 @@ private module ConditionalCompletionSplitting {
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = 0 }
- override predicate isEnabled(AstNode n) { this.appliesTo(n) }
+ override predicate isEnabled(ControlFlowElement n) { this.appliesTo(n) }
override string toString() { result = "ConditionalCompletion" }
}
@@ -45,47 +47,50 @@ private module ConditionalCompletionSplitting {
private class ConditionalCompletionSplitImpl extends SplitImpl, ConditionalCompletionSplit {
override ConditionalCompletionSplitKind getKind() { any() }
- override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
+ override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
(
- last(succ.(NotExpr).getOperand().getFullyConverted(), pred, c) and
+ astLast(succ.asAstNode().(NotExpr).getOperand().getFullyConverted(), pred, c) and
completion.(BooleanCompletion).getDual() = c
or
- last(succ.(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
+ astLast(succ.asAstNode().(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
or
- last(succ.(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
+ astLast(succ.asAstNode().(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
or
- succ =
+ succ.asAstNode() =
any(IfExpr ce |
- last(ce.getBranch(_).getFullyConverted(), pred, c) and
+ astLast(ce.getBranch(_).getFullyConverted(), pred, c) and
completion = c
)
or
- exists(Expr e |
- succ.(Exprs::Conversions::ConversionOrIdentityTree).convertsFrom(e) and
- last(e, pred, c) and
+ exists(Expr e, Exprs::Conversions::ConversionOrIdentityTree conv |
+ succ.asAstNode() = conv.getAst() and
+ conv.convertsFrom(e) and
+ astLast(e, pred, c) and
completion = c
)
)
}
- override predicate hasEntryScope(CfgScope scope, AstNode succ) { none() }
+ override predicate hasEntryScope(CfgScope scope, ControlFlowElement succ) { none() }
- override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
+ override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
- override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
+ override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
this.appliesTo(last) and
succExit(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
- override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
+ override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
+ none()
+ }
}
}
diff --git a/swift/ql/lib/codeql/swift/dataflow/Ssa.qll b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll
new file mode 100644
index 00000000000..9053428d4b0
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll
@@ -0,0 +1,69 @@
+cached
+module Ssa {
+ private import swift
+ private import internal.SsaImplCommon as SsaImplCommon
+ private import internal.SsaImplSpecific as SsaImplSpecific
+ private import codeql.swift.controlflow.CfgNodes
+ private import codeql.swift.controlflow.ControlFlowGraph
+ private import codeql.swift.controlflow.BasicBlocks
+
+ cached
+ class Definition extends SsaImplCommon::Definition {
+ cached
+ Location getLocation() { none() }
+
+ cached
+ ControlFlowNode getARead() {
+ exists(VarDecl v, BasicBlock bb, int i |
+ SsaImplCommon::ssaDefReachesRead(v, this, bb, i) and
+ SsaImplSpecific::variableRead(bb, i, v, true) and
+ result = bb.getNode(i)
+ )
+ }
+
+ cached
+ ControlFlowNode getAFirstRead() {
+ exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
+ this.definesAt(_, bb1, i1) and
+ SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
+ result = bb2.getNode(i2)
+ )
+ }
+
+ cached
+ predicate adjacentReadPair(ControlFlowNode read1, ControlFlowNode read2) {
+ exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
+ read1 = bb1.getNode(i1) and
+ SsaImplSpecific::variableRead(bb1, i1, _, true) and
+ SsaImplCommon::adjacentDefNoUncertainReads(this, bb1, i1, bb2, i2) and
+ read2 = bb2.getNode(i2)
+ )
+ }
+ }
+
+ cached
+ class WriteDefinition extends Definition, SsaImplCommon::WriteDefinition {
+ cached
+ override Location getLocation() {
+ exists(BasicBlock bb, int i |
+ this.definesAt(_, bb, i) and
+ result = bb.getNode(i).getLocation()
+ )
+ }
+
+ /**
+ * Holds if this SSA definition represents a direct assignment of `value`
+ * to the underlying variable.
+ */
+ cached
+ predicate assigns(ExprCfgNode value) {
+ exists(
+ AssignExpr a, BasicBlock bb, int i // TODO: use CFG node for assignment expr
+ |
+ this.definesAt(_, bb, i) and
+ a = bb.getNode(i).getNode().asAstNode() and
+ value.getNode().asAstNode() = a.getSource()
+ )
+ }
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index c393950de90..fc3321d2263 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -1,6 +1,8 @@
private import swift
private import DataFlowPublic
private import DataFlowDispatch
+private import codeql.swift.controlflow.CfgNodes
+private import codeql.swift.dataflow.Ssa
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(NodeImpl n) { result = n.getEnclosingCallable() }
@@ -25,22 +27,54 @@ abstract class NodeImpl extends Node {
abstract string toStringImpl();
}
+private class ExprNodeImpl extends ExprNode, NodeImpl {
+ override Location getLocationImpl() { result = expr.getLocation() }
+
+ override string toStringImpl() { result = expr.toString() }
+}
+
+private class SsaDefinitionNodeImpl extends SsaDefinitionNode, NodeImpl {
+ override Location getLocationImpl() { result = def.getLocation() }
+
+ override string toStringImpl() { result = def.toString() }
+}
+
/** A collection of cached types and predicates to be evaluated in the same stage. */
cached
private module Cached {
cached
- newtype TNode = TODO_TNode()
+ newtype TNode =
+ TExprNode(ExprCfgNode e) or
+ TNormalParameterNode(ParamDecl p) or
+ TSsaDefinitionNode(Ssa::Definition def)
+
+ private predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
+ exists(Ssa::Definition def |
+ // Step from assignment RHS to def
+ def.(Ssa::WriteDefinition).assigns(nodeFrom.getCfgNode()) and
+ nodeTo.asDefinition() = def
+ or
+ // step from def to first read
+ nodeFrom.asDefinition() = def and
+ nodeTo.getCfgNode() = def.getAFirstRead()
+ or
+ // use-use flow
+ def.adjacentReadPair(nodeFrom.getCfgNode(), nodeTo.getCfgNode())
+ )
+ }
/**
* This is the local flow predicate that is used as a building block in global
* data flow.
*/
cached
- predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { none() }
+ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
+ localFlowStepCommon(nodeFrom, nodeTo)
+ }
/** This is the local flow predicate that is exposed. */
cached
- predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) { none() }
+ predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) { localFlowStepCommon(nodeFrom, nodeTo) }
cached
newtype TContentSet = TODO_TContentSet()
@@ -58,6 +92,20 @@ private module ParameterNodes {
abstract class ParameterNodeImpl extends NodeImpl {
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { none() }
}
+
+ class NormalParameterNode extends ParameterNodeImpl, TNormalParameterNode {
+ ParamDecl param;
+
+ NormalParameterNode() { this = TNormalParameterNode(param) }
+
+ override Location getLocationImpl() { result = param.getLocation() }
+
+ override string toStringImpl() { result = param.toString() }
+
+ override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
+ none() // TODO
+ }
+ }
}
import ParameterNodes
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
index 4241640acff..70afd2651e1 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
@@ -3,6 +3,8 @@ private import DataFlowDispatch
private import DataFlowPrivate
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.BasicBlocks
+private import codeql.swift.controlflow.CfgNodes
+private import codeql.swift.dataflow.Ssa
/**
* An element, viewed as a node in a data flow graph. Either an expression
@@ -29,6 +31,21 @@ class Node extends TNode {
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
+
+ /**
+ * Gets this node's underlying expression, if any.
+ */
+ Expr asExpr() { none() }
+
+ /**
+ * Gets this data flow node's corresponding control flow node.
+ */
+ ControlFlowNode getCfgNode() { none() }
+
+ /**
+ * Gets this node's underlying SSA definition, if any.
+ */
+ Ssa::Definition asDefinition() { none() }
}
/**
@@ -38,13 +55,31 @@ class Node extends TNode {
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
-class ExprNode extends Node { }
+class ExprNode extends Node, TExprNode {
+ ExprCfgNode expr;
+
+ ExprNode() { this = TExprNode(expr) }
+
+ override Expr asExpr() { result = expr.getNode().asAstNode() }
+
+ override ControlFlowNode getCfgNode() { result = expr }
+}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNode extends Node { }
+class ParameterNode extends Node, TNormalParameterNode instanceof ParameterNodeImpl { }
+
+/**
+ */
+class SsaDefinitionNode extends Node, TSsaDefinitionNode {
+ Ssa::Definition def;
+
+ SsaDefinitionNode() { this = TSsaDefinitionNode(def) }
+
+ override Ssa::Definition asDefinition() { result = def }
+}
/**
* A node associated with an object after an operation that might have
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll
index 0eed5427740..bd7373935aa 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/SsaImplSpecific.qll
@@ -16,10 +16,17 @@ class SourceVariable = VarDecl;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignExpr assign |
- bb.getNode(i).getNode() = assign and
+ bb.getNode(i).getNode().asAstNode() = assign and
assign.getDest() = v.getAnAccess() and
certain = true
)
+ or
+ exists(PatternBindingDecl decl, Pattern pattern |
+ bb.getNode(i).getNode().asAstNode() = pattern and
+ decl.getAPattern() = pattern and
+ v.getParentPattern() = pattern and
+ certain = true
+ )
}
private predicate isLValue(DeclRefExpr ref) { any(AssignExpr assign).getDest() = ref }
@@ -27,7 +34,7 @@ private predicate isLValue(DeclRefExpr ref) { any(AssignExpr assign).getDest() =
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(DeclRefExpr ref |
not isLValue(ref) and
- bb.getNode(i).getNode() = ref and
+ bb.getNode(i).getNode().asAstNode() = ref and
v = ref.getDecl() and
certain = true
)
diff --git a/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll
index 2e7aac740b4..514cec194fc 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/AbstractFunctionDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.AbstractFunctionDecl
-class AbstractFunctionDecl extends AbstractFunctionDeclBase { }
+class AbstractFunctionDecl extends AbstractFunctionDeclBase {
+ override string toString() { result = this.getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll
index 1d885e0c4c3..bd1fb6b2998 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/AccessorDecl.qll
@@ -1,4 +1,32 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.AccessorDecl
-class AccessorDecl extends AccessorDeclBase { }
+private predicate isKnownAccessorKind(AccessorDecl decl, string kind) {
+ decl.isGetter() and kind = "get"
+ or
+ decl.isSetter() and kind = "set"
+ or
+ decl.isWillSet() and kind = "willSet"
+ or
+ decl.isDidSet() and kind = "didSet"
+}
+
+class AccessorDecl extends AccessorDeclBase {
+ predicate isPropertyObserver() {
+ this instanceof WillSetObserver or this instanceof DidSetObserver
+ }
+
+ override string toString() {
+ isKnownAccessorKind(this, result)
+ or
+ not isKnownAccessorKind(this, _) and
+ result = super.toString()
+ }
+}
+
+class WillSetObserver extends AccessorDecl {
+ WillSetObserver() { this.isWillSet() }
+}
+
+class DidSetObserver extends AccessorDecl {
+ DidSetObserver() { this.isDidSet() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll
index 375eff6acc3..6e34c2aa981 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.ConstructorDecl
-class ConstructorDecl extends ConstructorDeclBase { }
+class ConstructorDecl extends ConstructorDeclBase {
+ override string toString() { result = "deinit" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll
index 8cc68eaf7c8..9f08e1eab3b 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/DestructorDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.DestructorDecl
-class DestructorDecl extends DestructorDeclBase { }
+class DestructorDecl extends DestructorDeclBase {
+ override string toString() { result = "init" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/EnumCaseDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/EnumCaseDecl.qll
index 8af1fbe691c..d7aab6d9fe1 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/EnumCaseDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/EnumCaseDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.EnumCaseDecl
-class EnumCaseDecl extends EnumCaseDeclBase { }
+class EnumCaseDecl extends EnumCaseDeclBase {
+ override string toString() { result = "case ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/EnumElementDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/EnumElementDecl.qll
index e0322c530a4..965e0b3efdd 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/EnumElementDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/EnumElementDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.EnumElementDecl
-class EnumElementDecl extends EnumElementDeclBase { }
+class EnumElementDecl extends EnumElementDeclBase {
+ override string toString() { result = this.getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/ExtensionDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ExtensionDecl.qll
index 5f850f6a874..ce9e10da1af 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/ExtensionDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/ExtensionDecl.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.ExtensionDecl
-class ExtensionDecl extends ExtensionDeclBase { }
+class ExtensionDecl extends ExtensionDeclBase {
+ override string toString() {
+ result = "extension" // TODO: Once we extract the name of this one we can provide a better `toString`.
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/IfConfigDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/IfConfigDecl.qll
index d23143374e9..6fe6302658c 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/IfConfigDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/IfConfigDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.IfConfigDecl
-class IfConfigDecl extends IfConfigDeclBase { }
+class IfConfigDecl extends IfConfigDeclBase {
+ override string toString() { result = "#if ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/ImportDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ImportDecl.qll
index 6fca161a726..db687ecfad8 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/ImportDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/ImportDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.ImportDecl
-class ImportDecl extends ImportDeclBase { }
+class ImportDecl extends ImportDeclBase {
+ override string toString() { result = "import ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/OperatorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/OperatorDecl.qll
index 677ebf6b41e..592cdf4fd50 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/OperatorDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/OperatorDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.OperatorDecl
-class OperatorDecl extends OperatorDeclBase { }
+class OperatorDecl extends OperatorDeclBase {
+ override string toString() { result = this.getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/PatternBindingDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/PatternBindingDecl.qll
index d33a36b4c08..6bf9c021224 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/PatternBindingDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/PatternBindingDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.PatternBindingDecl
-class PatternBindingDecl extends PatternBindingDeclBase { }
+class PatternBindingDecl extends PatternBindingDeclBase {
+ override string toString() { result = "var ... = ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/PoundDiagnosticDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/PoundDiagnosticDecl.qll
index 9eedacc02bc..e80a0770dac 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/PoundDiagnosticDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/PoundDiagnosticDecl.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.PoundDiagnosticDecl
-class PoundDiagnosticDecl extends PoundDiagnosticDeclBase { }
+class PoundDiagnosticDecl extends PoundDiagnosticDeclBase {
+ override string toString() {
+ result = "#..." // TODO: Once we extract whether this is an error or a warning we can improve this.
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/PrecedenceGroupDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/PrecedenceGroupDecl.qll
index 9364d2b796e..b2e59fcb896 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/PrecedenceGroupDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/PrecedenceGroupDecl.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.PrecedenceGroupDecl
-class PrecedenceGroupDecl extends PrecedenceGroupDeclBase { }
+class PrecedenceGroupDecl extends PrecedenceGroupDeclBase {
+ override string toString() {
+ result = "precedencegroup ..." // TODO: Once we extract the name we can improve this.
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/SubscriptDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/SubscriptDecl.qll
index 9a44c97eb37..2da63cfb986 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/SubscriptDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/SubscriptDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.SubscriptDecl
-class SubscriptDecl extends SubscriptDeclBase { }
+class SubscriptDecl extends SubscriptDeclBase {
+ override string toString() { result = "subscript ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/TopLevelCodeDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/TopLevelCodeDecl.qll
index 606f5906473..a84dfec4dc0 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/TopLevelCodeDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/TopLevelCodeDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.TopLevelCodeDecl
-class TopLevelCodeDecl extends TopLevelCodeDeclBase { }
+class TopLevelCodeDecl extends TopLevelCodeDeclBase {
+ override string toString() { result = this.getBody().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll
index a7dfd753222..61012b16023 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.TypeDecl
-class TypeDecl extends TypeDeclBase { }
+class TypeDecl extends TypeDeclBase {
+ override string toString() { result = this.getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll
index f6940944c34..95a5801c1c1 100644
--- a/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll
+++ b/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll
@@ -1,4 +1,8 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.VarDecl
+private import codeql.swift.elements.expr.DeclRefExpr
-class VarDecl extends VarDeclBase { }
+class VarDecl extends VarDeclBase {
+ override string toString() { result = this.getName() }
+
+ DeclRefExpr getAnAccess() { result.getDecl() = this }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll
index a18cb4a6b92..27083d41ce3 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ApplyExpr.qll
@@ -4,4 +4,11 @@ private import codeql.swift.elements.expr.DeclRefExpr
class ApplyExpr extends ApplyExprBase {
FuncDecl getStaticTarget() { result = this.getFunction().(DeclRefExpr).getDecl() }
+
+ override string toString() {
+ result = "call to " + this.getStaticTarget().toString()
+ or
+ not exists(this.getStaticTarget()) and
+ result = "call to ..."
+ }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/Argument.qll b/swift/ql/lib/codeql/swift/elements/expr/Argument.qll
index a4d2229a1e3..c2a25b877a4 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/Argument.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/Argument.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.Argument
-class Argument extends ArgumentBase { }
+class Argument extends ArgumentBase {
+ override string toString() { result = this.getLabel() + ": " + this.getExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ArrayExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ArrayExpr.qll
index 8bb5f7222bf..8722a9ca601 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ArrayExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ArrayExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ArrayExpr
-class ArrayExpr extends ArrayExprBase { }
+class ArrayExpr extends ArrayExprBase {
+ override string toString() { result = "[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ArrowExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ArrowExpr.qll
index 301c0bdb557..94ea8624d68 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ArrowExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ArrowExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ArrowExpr
-class ArrowExpr extends ArrowExprBase { }
+class ArrowExpr extends ArrowExprBase {
+ override string toString() { result = "... -> ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/AssignExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/AssignExpr.qll
index d7d29d8682e..4669306bea1 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/AssignExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/AssignExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.AssignExpr
-class AssignExpr extends AssignExprBase { }
+class AssignExpr extends AssignExprBase {
+ override string toString() { result = " ... = ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/AutoClosureExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/AutoClosureExpr.qll
index 00113f026d5..8782a913cca 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/AutoClosureExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/AutoClosureExpr.qll
@@ -4,4 +4,6 @@ private import codeql.swift.elements.stmt.ReturnStmt
class AutoClosureExpr extends AutoClosureExprBase {
/** Gets the implicit return statement generated by this autoclosure expression. */
ReturnStmt getReturn() { result = unique( | | this.getBody().getAnElement()) }
+
+ override string toString() { result = this.getBody().toString() }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/AwaitExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/AwaitExpr.qll
index 76a17b9d181..378296432bc 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/AwaitExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/AwaitExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.AwaitExpr
-class AwaitExpr extends AwaitExprBase { }
+class AwaitExpr extends AwaitExprBase {
+ override string toString() { result = "await ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll
index 45116c436e4..2ce90e38bb9 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/BinaryExpr.qll
@@ -7,4 +7,6 @@ class BinaryExpr extends BinaryExprBase {
Expr getRightOperand() { result = this.getArgument(1).getExpr() }
Expr getAnOperand() { result = [this.getLeftOperand(), this.getRightOperand()] }
+
+ override string toString() { result = "... " + this.getFunction().toString() + " ..." }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/BindOptionalExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/BindOptionalExpr.qll
index 2b1aca34665..bcf3252ea17 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/BindOptionalExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/BindOptionalExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.BindOptionalExpr
-class BindOptionalExpr extends BindOptionalExprBase { }
+class BindOptionalExpr extends BindOptionalExprBase {
+ override string toString() { result = "...?" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/BooleanLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/BooleanLiteralExpr.qll
index d9a9902efa6..7f013a801dc 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/BooleanLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/BooleanLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.BooleanLiteralExpr
-class BooleanLiteralExpr extends BooleanLiteralExprBase { }
+class BooleanLiteralExpr extends BooleanLiteralExprBase {
+ override string toString() { result = this.getValue().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll
index 2495a22c892..c0fe030390d 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/CaptureListExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.CaptureListExpr
-class CaptureListExpr extends CaptureListExprBase { }
+class CaptureListExpr extends CaptureListExprBase {
+ override string toString() { result = this.getClosureBody().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ClosureExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ClosureExpr.qll
index 4f2158734ef..093deb19577 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ClosureExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ClosureExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ClosureExpr
-class ClosureExpr extends ClosureExprBase { }
+class ClosureExpr extends ClosureExprBase {
+ override string toString() { result = "{ ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DeclRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DeclRefExpr.qll
index 9531860838e..3e9ebb8d589 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DeclRefExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DeclRefExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DeclRefExpr
-class DeclRefExpr extends DeclRefExprBase { }
+class DeclRefExpr extends DeclRefExprBase {
+ override string toString() { result = this.getDecl().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DefaultArgumentExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DefaultArgumentExpr.qll
index bb1435c97e7..c61d2680d74 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DefaultArgumentExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DefaultArgumentExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DefaultArgumentExpr
-class DefaultArgumentExpr extends DefaultArgumentExprBase { }
+class DefaultArgumentExpr extends DefaultArgumentExprBase {
+ override string toString() { result = "default " + this.getParamDecl().getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DictionaryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DictionaryExpr.qll
index ac27502bf42..6f4edce8e45 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DictionaryExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DictionaryExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DictionaryExpr
-class DictionaryExpr extends DictionaryExprBase { }
+class DictionaryExpr extends DictionaryExprBase {
+ override string toString() { result = "[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DiscardAssignmentExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DiscardAssignmentExpr.qll
index 298fa78d708..a31c6167bb6 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DiscardAssignmentExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DiscardAssignmentExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DiscardAssignmentExpr
-class DiscardAssignmentExpr extends DiscardAssignmentExprBase { }
+class DiscardAssignmentExpr extends DiscardAssignmentExprBase {
+ override string toString() { result = "_" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DotSelfExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DotSelfExpr.qll
index ebbec08fe2b..a82f55cc422 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DotSelfExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DotSelfExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DotSelfExpr
-class DotSelfExpr extends DotSelfExprBase { }
+class DotSelfExpr extends DotSelfExprBase {
+ override string toString() { result = ".self" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll
index 74054ea1020..919bf1bfea1 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DotSyntaxBaseIgnoredExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DotSyntaxBaseIgnoredExpr
-class DotSyntaxBaseIgnoredExpr extends DotSyntaxBaseIgnoredExprBase { }
+class DotSyntaxBaseIgnoredExpr extends DotSyntaxBaseIgnoredExprBase {
+ override string toString() { result = "." + this.getSubExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DynamicMemberRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DynamicMemberRefExpr.qll
index e34a66e051f..757bc196e4d 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DynamicMemberRefExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DynamicMemberRefExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DynamicMemberRefExpr
-class DynamicMemberRefExpr extends DynamicMemberRefExprBase { }
+class DynamicMemberRefExpr extends DynamicMemberRefExprBase {
+ override string toString() { result = "." + this.getMember().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DynamicSubscriptExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DynamicSubscriptExpr.qll
index b3b19ed38b6..5114a6a4ebc 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DynamicSubscriptExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DynamicSubscriptExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DynamicSubscriptExpr
-class DynamicSubscriptExpr extends DynamicSubscriptExprBase { }
+class DynamicSubscriptExpr extends DynamicSubscriptExprBase {
+ override string toString() { result = this.getMember().toString() + "[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/DynamicTypeExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/DynamicTypeExpr.qll
index 9b72774a885..3af1f67b7bb 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/DynamicTypeExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/DynamicTypeExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.DynamicTypeExpr
-class DynamicTypeExpr extends DynamicTypeExprBase { }
+class DynamicTypeExpr extends DynamicTypeExprBase {
+ override string toString() { result = "type(of: ...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/EnumIsCaseExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/EnumIsCaseExpr.qll
index ee17c76f2b1..450fd199e49 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/EnumIsCaseExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/EnumIsCaseExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.EnumIsCaseExpr
-class EnumIsCaseExpr extends EnumIsCaseExprBase { }
+class EnumIsCaseExpr extends EnumIsCaseExprBase {
+ override string toString() { result = "... is " + this.getElement().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ExplicitCastExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ExplicitCastExpr.qll
index b6928dbd936..8c1923fdfbb 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ExplicitCastExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ExplicitCastExpr.qll
@@ -2,4 +2,6 @@ private import codeql.swift.generated.expr.ExplicitCastExpr
class ExplicitCastExpr extends ExplicitCastExprBase {
override predicate convertsFrom(Expr e) { explicit_cast_exprs(this, e) }
+
+ override string toString() { result = "(" + this.getType() + ") ..." }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/FloatLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/FloatLiteralExpr.qll
index 91240e43acf..5a40548d1fc 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/FloatLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/FloatLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.FloatLiteralExpr
-class FloatLiteralExpr extends FloatLiteralExprBase { }
+class FloatLiteralExpr extends FloatLiteralExprBase {
+ override string toString() { result = this.getStringValue() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ForceTryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ForceTryExpr.qll
index 3f9ee33a2b8..90a1d4f82b6 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ForceTryExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ForceTryExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ForceTryExpr
-class ForceTryExpr extends ForceTryExprBase { }
+class ForceTryExpr extends ForceTryExprBase {
+ override string toString() { result = "try! ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ForceValueExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ForceValueExpr.qll
index c2b13fdbef4..bdb0645226b 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ForceValueExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ForceValueExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ForceValueExpr
-class ForceValueExpr extends ForceValueExprBase { }
+class ForceValueExpr extends ForceValueExprBase {
+ override string toString() { result = "...!" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/IfExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/IfExpr.qll
index 75d41d3b484..10a8a098180 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/IfExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/IfExpr.qll
@@ -8,4 +8,6 @@ class IfExpr extends IfExprBase {
b = false and
result = this.getElseExpr()
}
+
+ override string toString() { result = "... ? ... : ..." }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ImplicitConversionExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ImplicitConversionExpr.qll
index ca00b7ec7ed..f8c2285978a 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ImplicitConversionExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ImplicitConversionExpr.qll
@@ -2,4 +2,6 @@ private import codeql.swift.generated.expr.ImplicitConversionExpr
class ImplicitConversionExpr extends ImplicitConversionExprBase {
override predicate convertsFrom(Expr e) { implicit_conversion_exprs(this, e) }
+
+ override string toString() { result = "(" + this.getType().toString() + ") ..." }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/InOutExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/InOutExpr.qll
index f4a29e0e1cc..f1e40ed36fe 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/InOutExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/InOutExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.InOutExpr
-class InOutExpr extends InOutExprBase { }
+class InOutExpr extends InOutExprBase {
+ override string toString() { result = "&..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/IntegerLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/IntegerLiteralExpr.qll
index 121b1b9e3b3..87e7bdffae2 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/IntegerLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/IntegerLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.IntegerLiteralExpr
-class IntegerLiteralExpr extends IntegerLiteralExprBase { }
+class IntegerLiteralExpr extends IntegerLiteralExprBase {
+ override string toString() { result = this.getStringValue() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/InterpolatedStringLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/InterpolatedStringLiteralExpr.qll
index 3095dc12001..599d780357f 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/InterpolatedStringLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/InterpolatedStringLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.InterpolatedStringLiteralExpr
-class InterpolatedStringLiteralExpr extends InterpolatedStringLiteralExprBase { }
+class InterpolatedStringLiteralExpr extends InterpolatedStringLiteralExprBase {
+ override string toString() { result = "\"...\"" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/IsExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/IsExpr.qll
index e823adc489c..d87fc7fe05a 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/IsExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/IsExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.IsExpr
-class IsExpr extends IsExprBase { }
+class IsExpr extends IsExprBase {
+ override string toString() { result = "... is ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/KeyPathApplicationExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/KeyPathApplicationExpr.qll
index 857981bbe5c..80c0f1d5678 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/KeyPathApplicationExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/KeyPathApplicationExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.KeyPathApplicationExpr
-class KeyPathApplicationExpr extends KeyPathApplicationExprBase { }
+class KeyPathApplicationExpr extends KeyPathApplicationExprBase {
+ override string toString() { result = "\\...[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/KeyPathDotExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/KeyPathDotExpr.qll
index 2882cbc4d87..18bd4ee4186 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/KeyPathDotExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/KeyPathDotExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.KeyPathDotExpr
-class KeyPathDotExpr extends KeyPathDotExprBase { }
+class KeyPathDotExpr extends KeyPathDotExprBase {
+ override string toString() { result = "\\...." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/KeyPathExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/KeyPathExpr.qll
index 4c7ef30c882..4869ac44bde 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/KeyPathExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/KeyPathExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.KeyPathExpr
-class KeyPathExpr extends KeyPathExprBase { }
+class KeyPathExpr extends KeyPathExprBase {
+ override string toString() { result = "#keyPath(...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll
index 55e2398782a..9564ece75e3 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/LazyInitializerExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.LazyInitializerExpr
-class LazyInitializerExpr extends LazyInitializerExprBase { }
+class LazyInitializerExpr extends LazyInitializerExprBase {
+ override string toString() { result = this.getSubExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/MagicIdentifierLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/MagicIdentifierLiteralExpr.qll
index 3fa5f6f1341..fd435f47dce 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/MagicIdentifierLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/MagicIdentifierLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.MagicIdentifierLiteralExpr
-class MagicIdentifierLiteralExpr extends MagicIdentifierLiteralExprBase { }
+class MagicIdentifierLiteralExpr extends MagicIdentifierLiteralExprBase {
+ override string toString() { result = "#..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/MakeTemporarilyEscapableExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/MakeTemporarilyEscapableExpr.qll
index 085a6d213a6..342a799e1c9 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/MakeTemporarilyEscapableExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/MakeTemporarilyEscapableExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.MakeTemporarilyEscapableExpr
-class MakeTemporarilyEscapableExpr extends MakeTemporarilyEscapableExprBase { }
+class MakeTemporarilyEscapableExpr extends MakeTemporarilyEscapableExprBase {
+ override string toString() { result = this.getSubExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/MemberRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/MemberRefExpr.qll
index a85e5c8766d..fa56b0b8fba 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/MemberRefExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/MemberRefExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.MemberRefExpr
-class MemberRefExpr extends MemberRefExprBase { }
+class MemberRefExpr extends MemberRefExprBase {
+ override string toString() { result = "." + this.getMember().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/NilLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/NilLiteralExpr.qll
index bd4731de537..a2e2281888f 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/NilLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/NilLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.NilLiteralExpr
-class NilLiteralExpr extends NilLiteralExprBase { }
+class NilLiteralExpr extends NilLiteralExprBase {
+ override string toString() { result = "nil" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ObjCSelectorExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ObjCSelectorExpr.qll
index 8a4a8d34b69..45ccb04ee55 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ObjCSelectorExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ObjCSelectorExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ObjCSelectorExpr
-class ObjCSelectorExpr extends ObjCSelectorExprBase { }
+class ObjCSelectorExpr extends ObjCSelectorExprBase {
+ override string toString() { result = "#selector(...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ObjectLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ObjectLiteralExpr.qll
index 28702427376..61e2408c79c 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ObjectLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ObjectLiteralExpr.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ObjectLiteralExpr
-class ObjectLiteralExpr extends ObjectLiteralExprBase { }
+class ObjectLiteralExpr extends ObjectLiteralExprBase {
+ override string toString() {
+ result = "#...(...)" // TOOD: We can improve this once we extract the kind
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/OneWayExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/OneWayExpr.qll
index 702e661bba0..a10c3e4187e 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/OneWayExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/OneWayExpr.qll
@@ -2,4 +2,6 @@ private import codeql.swift.generated.expr.OneWayExpr
class OneWayExpr extends OneWayExprBase {
override predicate convertsFrom(Expr e) { one_way_exprs(this, e) }
+
+ override string toString() { result = this.getSubExpr().toString() }
}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/OptionalTryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/OptionalTryExpr.qll
index 56bba573716..eb643b70079 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/OptionalTryExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/OptionalTryExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.OptionalTryExpr
-class OptionalTryExpr extends OptionalTryExprBase { }
+class OptionalTryExpr extends OptionalTryExprBase {
+ override string toString() { result = "try? ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll
index 2cfbd3ea4d9..f8b309ed3d0 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/OtherConstructorDeclRefExpr.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.OtherConstructorDeclRefExpr
-class OtherConstructorDeclRefExpr extends OtherConstructorDeclRefExprBase { }
+class OtherConstructorDeclRefExpr extends OtherConstructorDeclRefExprBase {
+ override string toString() {
+ result = "call to ..." // TODO: We can make this better once we extract the constructor call
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/ParenExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/ParenExpr.qll
index 7b0b8178c53..763a7106b98 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/ParenExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/ParenExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.ParenExpr
-class ParenExpr extends ParenExprBase { }
+class ParenExpr extends ParenExprBase {
+ override string toString() { result = "(...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll
index 5aa2711801d..8f42cf72c9e 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/RebindSelfInConstructorExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.RebindSelfInConstructorExpr
-class RebindSelfInConstructorExpr extends RebindSelfInConstructorExprBase { }
+class RebindSelfInConstructorExpr extends RebindSelfInConstructorExprBase {
+ override string toString() { result = "self = ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/RegexLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/RegexLiteralExpr.qll
index ef087bc1681..dcb91129ca7 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/RegexLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/RegexLiteralExpr.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.RegexLiteralExpr
-class RegexLiteralExpr extends RegexLiteralExprBase { }
+class RegexLiteralExpr extends RegexLiteralExprBase {
+ override string toString() {
+ result = "..." // TODO: We can improve this once we extract the regex
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/StringLiteralExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/StringLiteralExpr.qll
index cd2ff43a039..23b5dbab7bd 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/StringLiteralExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/StringLiteralExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.StringLiteralExpr
-class StringLiteralExpr extends StringLiteralExprBase { }
+class StringLiteralExpr extends StringLiteralExprBase {
+ override string toString() { result = this.getValue() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/SubscriptExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/SubscriptExpr.qll
index 8ae51baae26..4d681e189de 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/SubscriptExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/SubscriptExpr.qll
@@ -1,4 +1,19 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.SubscriptExpr
-class SubscriptExpr extends SubscriptExprBase { }
+class SubscriptExpr extends SubscriptExprBase {
+ Argument getFirstArgument() {
+ exists(int i |
+ result = this.getArgument(i) and
+ not exists(this.getArgument(i - 1))
+ )
+ }
+
+ Argument getLastArgument() {
+ exists(int i |
+ result = this.getArgument(i) and
+ not exists(this.getArgument(i + 1))
+ )
+ }
+
+ override string toString() { result = "...[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll
index 292431be730..2a2def26a84 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/SuperRefExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.SuperRefExpr
-class SuperRefExpr extends SuperRefExprBase { }
+class SuperRefExpr extends SuperRefExprBase {
+ override string toString() { result = "super" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/TryExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/TryExpr.qll
index 0c9fc51cfe0..76a23bb2a7b 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/TryExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/TryExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.TryExpr
-class TryExpr extends TryExprBase { }
+class TryExpr extends TryExprBase {
+ override string toString() { result = "try ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/TupleElementExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/TupleElementExpr.qll
index 9e92dae7f00..f021deae540 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/TupleElementExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/TupleElementExpr.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.TupleElementExpr
-class TupleElementExpr extends TupleElementExprBase { }
+class TupleElementExpr extends TupleElementExprBase {
+ override string toString() {
+ result = "." + this.getIndex() // TODO: Can be improved once we extract the name
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/TupleExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/TupleExpr.qll
index 1ffe11cf28b..c8465638645 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/TupleExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/TupleExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.TupleExpr
-class TupleExpr extends TupleExprBase { }
+class TupleExpr extends TupleExprBase {
+ override string toString() { result = "(...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/TypeExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/TypeExpr.qll
index 9ecde1d026d..ad9077a4c25 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/TypeExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/TypeExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.TypeExpr
-class TypeExpr extends TypeExprBase { }
+class TypeExpr extends TypeExprBase {
+ override string toString() { result = this.getType().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/expr/VarargExpansionExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/VarargExpansionExpr.qll
index 0769e7ce6dd..200c8735f07 100644
--- a/swift/ql/lib/codeql/swift/elements/expr/VarargExpansionExpr.qll
+++ b/swift/ql/lib/codeql/swift/elements/expr/VarargExpansionExpr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.VarargExpansionExpr
-class VarargExpansionExpr extends VarargExpansionExprBase { }
+class VarargExpansionExpr extends VarargExpansionExprBase {
+ override string toString() { result = this.getSubExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/AnyPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/AnyPattern.qll
index 3db71bff5db..f2f62d42906 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/AnyPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/AnyPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.AnyPattern
-class AnyPattern extends AnyPatternBase { }
+class AnyPattern extends AnyPatternBase {
+ override string toString() { result = "_" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll
index 2c9d534942b..ef081d052c6 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.BindingPattern
-class BindingPattern extends BindingPatternBase { }
+class BindingPattern extends BindingPatternBase {
+ override string toString() { result = "let ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/BoolPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/BoolPattern.qll
index 69e915e0ac6..5fa2ec249a8 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/BoolPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/BoolPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.BoolPattern
-class BoolPattern extends BoolPatternBase { }
+class BoolPattern extends BoolPatternBase {
+ override string toString() { result = this.getValue().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll
index 4a8d71ab603..0244bce6cd3 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll
@@ -1,4 +1,9 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.EnumElementPattern
-class EnumElementPattern extends EnumElementPatternBase { }
+class EnumElementPattern extends EnumElementPatternBase {
+ override string toString() {
+ if this.hasSubPattern()
+ then result = "." + this.getElement().toString() + "(...)"
+ else result = "." + this.getElement().toString()
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/ExprPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/ExprPattern.qll
index 55ab31a698f..87f5b748622 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/ExprPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/ExprPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.ExprPattern
-class ExprPattern extends ExprPatternBase { }
+class ExprPattern extends ExprPatternBase {
+ override string toString() { result = this.getSubExpr().toString() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/IsPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/IsPattern.qll
index e5b9fc22e53..b1a9594c927 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/IsPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/IsPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.IsPattern
-class IsPattern extends IsPatternBase { }
+class IsPattern extends IsPatternBase {
+ override string toString() { result = "... is ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll
index bfd06575bb9..7f980677196 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.NamedPattern
-class NamedPattern extends NamedPatternBase { }
+class NamedPattern extends NamedPatternBase {
+ override string toString() { result = this.getName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/OptionalSomePattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/OptionalSomePattern.qll
index acd3ee82477..9fb71e55d6f 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/OptionalSomePattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/OptionalSomePattern.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.OptionalSomePattern
-class OptionalSomePattern extends OptionalSomePatternBase { }
+class OptionalSomePattern extends OptionalSomePatternBase {
+ override string toString() { result = "let ...?" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/ParenPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/ParenPattern.qll
index 8d5c6db26fa..8f518e43d31 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/ParenPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/ParenPattern.qll
@@ -2,4 +2,6 @@ private import codeql.swift.generated.pattern.ParenPattern
class ParenPattern extends ParenPatternBase {
final override Pattern getResolveStep() { paren_patterns(this, result) }
+
+ override string toString() { result = "(...)" }
}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/TuplePattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/TuplePattern.qll
index a09c5040b3b..fcd7f7fc238 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/TuplePattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/TuplePattern.qll
@@ -9,4 +9,6 @@ class TuplePattern extends TuplePatternBase {
not exists(this.getElement(i + 1))
)
}
+
+ override string toString() { result = "(...)" }
}
diff --git a/swift/ql/lib/codeql/swift/elements/pattern/TypedPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/TypedPattern.qll
index 95fea7f2302..728dede4977 100644
--- a/swift/ql/lib/codeql/swift/elements/pattern/TypedPattern.qll
+++ b/swift/ql/lib/codeql/swift/elements/pattern/TypedPattern.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.pattern.TypedPattern
-class TypedPattern extends TypedPatternBase { }
+class TypedPattern extends TypedPatternBase {
+ override string toString() {
+ if exists(this.getSubPattern()) then result = "... as ..." else result = "is ..."
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/BraceStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/BraceStmt.qll
index a0f497bb7c0..d22afad3efa 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/BraceStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/BraceStmt.qll
@@ -9,4 +9,6 @@ class BraceStmt extends BraceStmtBase {
not exists(this.getElement(i + 1))
)
}
+
+ override string toString() { result = "{ ... }" }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/BreakStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/BreakStmt.qll
index 7a756b97656..02caf1b8cc8 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/BreakStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/BreakStmt.qll
@@ -1,4 +1,10 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.BreakStmt
-class BreakStmt extends BreakStmtBase { }
+class BreakStmt extends BreakStmtBase {
+ override string toString() {
+ result = "break " + this.getTargetName()
+ or
+ not this.hasTargetName() and
+ result = "break"
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/CaseLabelItem.qll b/swift/ql/lib/codeql/swift/elements/stmt/CaseLabelItem.qll
index 98b410005a1..8a8ea2e358e 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/CaseLabelItem.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/CaseLabelItem.qll
@@ -1,4 +1,9 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.CaseLabelItem
-class CaseLabelItem extends CaseLabelItemBase { }
+class CaseLabelItem extends CaseLabelItemBase {
+ override string toString() {
+ if this.hasGuard()
+ then result = this.getPattern().toString() + " where ..."
+ else result = this.getPattern().toString()
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/CaseStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/CaseStmt.qll
index 3e9ba6acfd1..b2f3d5d952f 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/CaseStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/CaseStmt.qll
@@ -9,4 +9,6 @@ class CaseStmt extends CaseStmtBase {
not exists(this.getLabel(i + 1))
)
}
+
+ override string toString() { result = "case ..." }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/ConditionElement.qll b/swift/ql/lib/codeql/swift/elements/stmt/ConditionElement.qll
index e41f0d706e4..d11c1ef668b 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/ConditionElement.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/ConditionElement.qll
@@ -9,4 +9,6 @@ class ConditionElement extends ConditionElementBase {
or
result = this.getPattern()
}
+
+ override string toString() { result = this.getUnderlyingCondition().toString() }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/ContinueStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/ContinueStmt.qll
index b31996ae298..9e0dbc7eb65 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/ContinueStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/ContinueStmt.qll
@@ -1,4 +1,10 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.ContinueStmt
-class ContinueStmt extends ContinueStmtBase { }
+class ContinueStmt extends ContinueStmtBase {
+ override string toString() {
+ result = "continue " + this.getTargetName()
+ or
+ not this.hasTargetName() and
+ result = "continue"
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/DeferStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/DeferStmt.qll
index 69fd1f37d96..017b13e6d59 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/DeferStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/DeferStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.DeferStmt
-class DeferStmt extends DeferStmtBase { }
+class DeferStmt extends DeferStmtBase {
+ override string toString() { result = "defer { ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/DoCatchStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/DoCatchStmt.qll
index b9d437d5725..c9fa1f85794 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/DoCatchStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/DoCatchStmt.qll
@@ -9,4 +9,6 @@ class DoCatchStmt extends DoCatchStmtBase {
not exists(this.getCatch(i + 1))
)
}
+
+ override string toString() { result = "do { ... } catch { ... }" }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/DoStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/DoStmt.qll
index c6cdd8af01f..057abb1d8c5 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/DoStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/DoStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.DoStmt
-class DoStmt extends DoStmtBase { }
+class DoStmt extends DoStmtBase {
+ override string toString() { result = "do { ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/FailStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/FailStmt.qll
index 568d812c506..c6ca7a0c923 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/FailStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/FailStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.FailStmt
-class FailStmt extends FailStmtBase { }
+class FailStmt extends FailStmtBase {
+ override string toString() { result = "fail" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/FallthroughStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/FallthroughStmt.qll
index 9c8c21b8ffc..50a81c511f2 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/FallthroughStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/FallthroughStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.FallthroughStmt
-class FallthroughStmt extends FallthroughStmtBase { }
+class FallthroughStmt extends FallthroughStmtBase {
+ override string toString() { result = "fallthrough" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/ForEachStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/ForEachStmt.qll
index 5a89881ee25..9024cea2cd2 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/ForEachStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/ForEachStmt.qll
@@ -1,4 +1,9 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.ForEachStmt
-class ForEachStmt extends ForEachStmtBase { }
+class ForEachStmt extends ForEachStmtBase {
+ override string toString() {
+ if this.hasWhere()
+ then result = "for ... in ... where ... { ... }"
+ else result = "for ... in ... { ... }"
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/GuardStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/GuardStmt.qll
index 5604fa2388c..d2955b3d294 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/GuardStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/GuardStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.GuardStmt
-class GuardStmt extends GuardStmtBase { }
+class GuardStmt extends GuardStmtBase {
+ override string toString() { result = "guard ... else { ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/IfStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/IfStmt.qll
index ebd428bba5c..d7b274f3d21 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/IfStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/IfStmt.qll
@@ -13,4 +13,10 @@ class IfStmt extends IfStmtBase {
b = false and
result = this.getElse()
}
+
+ override string toString() {
+ if this.hasElse()
+ then result = "if ... then { ... } else { ... }"
+ else result = "if ... then { ... }"
+ }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/LabeledStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/LabeledStmt.qll
index 36c1c391db9..77bbe2129ad 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/LabeledStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/LabeledStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.LabeledStmt
-class LabeledStmt extends LabeledStmtBase { }
+class LabeledStmt extends LabeledStmtBase {
+ override string toString() { result = this.getLabel() + ": ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/PoundAssertStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/PoundAssertStmt.qll
index c65b5f02440..f2d9f2d74df 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/PoundAssertStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/PoundAssertStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.PoundAssertStmt
-class PoundAssertStmt extends PoundAssertStmtBase { }
+class PoundAssertStmt extends PoundAssertStmtBase {
+ override string toString() { result = "#assert ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/RepeatWhileStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/RepeatWhileStmt.qll
index 5de20648269..6bc3c44ec3a 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/RepeatWhileStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/RepeatWhileStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.RepeatWhileStmt
-class RepeatWhileStmt extends RepeatWhileStmtBase { }
+class RepeatWhileStmt extends RepeatWhileStmtBase {
+ override string toString() { result = "repeat { ... } while ... " }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/ReturnStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/ReturnStmt.qll
index 6ab3177f80d..ba3762a23bc 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/ReturnStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/ReturnStmt.qll
@@ -1,4 +1,7 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.ReturnStmt
-class ReturnStmt extends ReturnStmtBase { }
+class ReturnStmt extends ReturnStmtBase {
+ override string toString() {
+ if this.hasResult() then result = "return ..." else result = "return"
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/SwitchStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/SwitchStmt.qll
index 11077d87e77..e71a211d69f 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/SwitchStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/SwitchStmt.qll
@@ -9,4 +9,6 @@ class SwitchStmt extends SwitchStmtBase {
not exists(this.getCase(i + 1))
)
}
+
+ override string toString() { result = "switch " + this.getExpr().toString() + " { ... }" }
}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/ThrowStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/ThrowStmt.qll
index 1991fac6e97..9296fd4d05c 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/ThrowStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/ThrowStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.ThrowStmt
-class ThrowStmt extends ThrowStmtBase { }
+class ThrowStmt extends ThrowStmtBase {
+ override string toString() { result = "throw ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/WhileStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/WhileStmt.qll
index 29aa526ea7e..28ff0bc1f66 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/WhileStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/WhileStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.WhileStmt
-class WhileStmt extends WhileStmtBase { }
+class WhileStmt extends WhileStmtBase {
+ override string toString() { result = "while ... { ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/stmt/YieldStmt.qll b/swift/ql/lib/codeql/swift/elements/stmt/YieldStmt.qll
index 812e77fee99..6380e6ddb61 100644
--- a/swift/ql/lib/codeql/swift/elements/stmt/YieldStmt.qll
+++ b/swift/ql/lib/codeql/swift/elements/stmt/YieldStmt.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.stmt.YieldStmt
-class YieldStmt extends YieldStmtBase { }
+class YieldStmt extends YieldStmtBase {
+ override string toString() { result = "yield ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/type/Type.qll b/swift/ql/lib/codeql/swift/elements/type/Type.qll
index 50e9b94c746..264a32091e4 100644
--- a/swift/ql/lib/codeql/swift/elements/type/Type.qll
+++ b/swift/ql/lib/codeql/swift/elements/type/Type.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.type.Type
-class Type extends TypeBase { }
+class Type extends TypeBase {
+ override string toString() { result = this.getDiagnosticsName() }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/ArrayTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/ArrayTypeRepr.qll
index 84f2705b6fe..551e846daad 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/ArrayTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/ArrayTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ArrayTypeRepr
-class ArrayTypeRepr extends ArrayTypeReprBase { }
+class ArrayTypeRepr extends ArrayTypeReprBase {
+ override string toString() { result = "[...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/AttributedTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/AttributedTypeRepr.qll
index 73d3ea97b8f..96ae6d613fc 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/AttributedTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/AttributedTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.AttributedTypeRepr
-class AttributedTypeRepr extends AttributedTypeReprBase { }
+class AttributedTypeRepr extends AttributedTypeReprBase {
+ override string toString() { result = "@..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/CompileTimeConstTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/CompileTimeConstTypeRepr.qll
index 4235ccbcf50..0527a978c92 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/CompileTimeConstTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/CompileTimeConstTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.CompileTimeConstTypeRepr
-class CompileTimeConstTypeRepr extends CompileTimeConstTypeReprBase { }
+class CompileTimeConstTypeRepr extends CompileTimeConstTypeReprBase {
+ override string toString() { result = "_const ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/CompoundIdentTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/CompoundIdentTypeRepr.qll
index aafc54489ac..6b0270e074f 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/CompoundIdentTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/CompoundIdentTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.CompoundIdentTypeRepr
-class CompoundIdentTypeRepr extends CompoundIdentTypeReprBase { }
+class CompoundIdentTypeRepr extends CompoundIdentTypeReprBase {
+ override string toString() { result = "...<...>" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/DictionaryTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/DictionaryTypeRepr.qll
index a226c72c1d1..d28f8e972e1 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/DictionaryTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/DictionaryTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.DictionaryTypeRepr
-class DictionaryTypeRepr extends DictionaryTypeReprBase { }
+class DictionaryTypeRepr extends DictionaryTypeReprBase {
+ override string toString() { result = "[... : ...]" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/FunctionTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/FunctionTypeRepr.qll
index 96cba609393..4441903d045 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/FunctionTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/FunctionTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.FunctionTypeRepr
-class FunctionTypeRepr extends FunctionTypeReprBase { }
+class FunctionTypeRepr extends FunctionTypeReprBase {
+ override string toString() { result = "... -> ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/GenericIdentTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/GenericIdentTypeRepr.qll
index 48774afb51b..54e388d5e7b 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/GenericIdentTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/GenericIdentTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.GenericIdentTypeRepr
-class GenericIdentTypeRepr extends GenericIdentTypeReprBase { }
+class GenericIdentTypeRepr extends GenericIdentTypeReprBase {
+ override string toString() { result = "...<...>" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/ImplicitlyUnwrappedOptionalTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/ImplicitlyUnwrappedOptionalTypeRepr.qll
index d04f438d676..ace8103e1ca 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/ImplicitlyUnwrappedOptionalTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/ImplicitlyUnwrappedOptionalTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ImplicitlyUnwrappedOptionalTypeRepr
-class ImplicitlyUnwrappedOptionalTypeRepr extends ImplicitlyUnwrappedOptionalTypeReprBase { }
+class ImplicitlyUnwrappedOptionalTypeRepr extends ImplicitlyUnwrappedOptionalTypeReprBase {
+ override string toString() { result = "...!" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/InOutTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/InOutTypeRepr.qll
index 3c17987ccb1..3be97d2f9fa 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/InOutTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/InOutTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.InOutTypeRepr
-class InOutTypeRepr extends InOutTypeReprBase { }
+class InOutTypeRepr extends InOutTypeReprBase {
+ override string toString() { result = "inout ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/IsolatedTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/IsolatedTypeRepr.qll
index 1ba568bb793..d7a9eb48345 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/IsolatedTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/IsolatedTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.IsolatedTypeRepr
-class IsolatedTypeRepr extends IsolatedTypeReprBase { }
+class IsolatedTypeRepr extends IsolatedTypeReprBase {
+ override string toString() { result = "isolated ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/MetatypeTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/MetatypeTypeRepr.qll
index 6eb6f16f733..f48ac07816d 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/MetatypeTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/MetatypeTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.MetatypeTypeRepr
-class MetatypeTypeRepr extends MetatypeTypeReprBase { }
+class MetatypeTypeRepr extends MetatypeTypeReprBase {
+ override string toString() { result = ".Type" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/OptionalTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/OptionalTypeRepr.qll
index 840cd191f52..b9046b00955 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/OptionalTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/OptionalTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.OptionalTypeRepr
-class OptionalTypeRepr extends OptionalTypeReprBase { }
+class OptionalTypeRepr extends OptionalTypeReprBase {
+ override string toString() { result = "...?" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/OwnedTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/OwnedTypeRepr.qll
index 4221a66b762..88e90d479d7 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/OwnedTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/OwnedTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.OwnedTypeRepr
-class OwnedTypeRepr extends OwnedTypeReprBase { }
+class OwnedTypeRepr extends OwnedTypeReprBase {
+ override string toString() { result = "owned ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/ProtocolTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/ProtocolTypeRepr.qll
index ca229b0fad5..8701fceaf53 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/ProtocolTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/ProtocolTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ProtocolTypeRepr
-class ProtocolTypeRepr extends ProtocolTypeReprBase { }
+class ProtocolTypeRepr extends ProtocolTypeReprBase {
+ override string toString() { result = ".Protocol" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/SharedTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/SharedTypeRepr.qll
index a2ab0f3a6fe..ed31dc0bf10 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/SharedTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/SharedTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SharedTypeRepr
-class SharedTypeRepr extends SharedTypeReprBase { }
+class SharedTypeRepr extends SharedTypeReprBase {
+ override string toString() { result = "shared ..." }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/SilBoxTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/SilBoxTypeRepr.qll
index f792f2fa348..7949d10849b 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/SilBoxTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/SilBoxTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SilBoxTypeRepr
-class SilBoxTypeRepr extends SilBoxTypeReprBase { }
+class SilBoxTypeRepr extends SilBoxTypeReprBase {
+ override string toString() { result = "{ ... }" }
+}
diff --git a/swift/ql/lib/codeql/swift/elements/typerepr/TupleTypeRepr.qll b/swift/ql/lib/codeql/swift/elements/typerepr/TupleTypeRepr.qll
index 44614dab3d2..745fb39b9e5 100644
--- a/swift/ql/lib/codeql/swift/elements/typerepr/TupleTypeRepr.qll
+++ b/swift/ql/lib/codeql/swift/elements/typerepr/TupleTypeRepr.qll
@@ -1,4 +1,5 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.TupleTypeRepr
-class TupleTypeRepr extends TupleTypeReprBase { }
+class TupleTypeRepr extends TupleTypeReprBase {
+ override string toString() { result = "(...)" }
+}
diff --git a/swift/ql/lib/codeql/swift/generated/type/AnyFunctionType.qll b/swift/ql/lib/codeql/swift/generated/type/AnyFunctionType.qll
index 6add8032bc1..da547ce7aac 100644
--- a/swift/ql/lib/codeql/swift/generated/type/AnyFunctionType.qll
+++ b/swift/ql/lib/codeql/swift/generated/type/AnyFunctionType.qll
@@ -27,4 +27,6 @@ class AnyFunctionTypeBase extends @any_function_type, Type {
int getNumberOfParamLabels() { result = count(getAParamLabel()) }
predicate isThrowing() { any_function_type_is_throwing(this) }
+
+ predicate isAsync() { any_function_type_is_async(this) }
}
diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme
index d9497443044..47edbb550e8 100644
--- a/swift/ql/lib/swift.dbscheme
+++ b/swift/ql/lib/swift.dbscheme
@@ -176,6 +176,11 @@ any_function_type_is_throwing(
int id: @any_function_type ref
);
+#keyset[id]
+any_function_type_is_async(
+ int id: @any_function_type ref
+);
+
@any_generic_type =
@nominal_or_bound_generic_nominal_type
| @unbound_generic_type
diff --git a/swift/ql/test/extractor-tests/declarations/accessor.expected b/swift/ql/test/extractor-tests/declarations/accessor.expected
index 66db1b8fd0f..d47ce163c5d 100644
--- a/swift/ql/test/extractor-tests/declarations/accessor.expected
+++ b/swift/ql/test/extractor-tests/declarations/accessor.expected
@@ -1,53 +1,53 @@
-| test.swift:2:7:2:7 | AccessorDecl | ? |
-| test.swift:2:7:2:7 | AccessorDecl | get |
-| test.swift:2:7:2:7 | AccessorDecl | set |
-| test.swift:3:7:3:7 | AccessorDecl | ? |
-| test.swift:4:5:4:24 | AccessorDecl | get |
-| test.swift:5:5:5:38 | AccessorDecl | set |
-| test.swift:9:17:9:17 | AccessorDecl | ? |
-| test.swift:9:17:9:17 | AccessorDecl | get |
-| test.swift:9:17:9:17 | AccessorDecl | set |
-| test.swift:23:9:23:9 | AccessorDecl | ? |
-| test.swift:23:31:23:31 | AccessorDecl | get |
-| test.swift:23:35:23:35 | AccessorDecl | set |
-| test.swift:24:40:24:40 | AccessorDecl | get |
-| test.swift:32:3:34:3 | AccessorDecl | get |
-| test.swift:35:3:35:18 | AccessorDecl | set |
-| test.swift:41:7:41:7 | AccessorDecl | ? |
-| test.swift:41:7:41:7 | AccessorDecl | get |
-| test.swift:41:7:41:7 | AccessorDecl | set |
-| test.swift:70:5:72:5 | AccessorDecl | get |
-| test.swift:77:20:77:20 | AccessorDecl | get |
-| test.swift:82:7:82:7 | AccessorDecl | ? |
-| test.swift:83:5:83:11 | AccessorDecl | set |
-| test.swift:84:5:86:5 | AccessorDecl | get |
-| test.swift:91:27:93:3 | AccessorDecl | get |
-| test.swift:97:5:99:5 | AccessorDecl | get |
-| test.swift:102:7:102:7 | AccessorDecl | ? |
-| test.swift:102:7:102:7 | AccessorDecl | get |
-| test.swift:102:7:102:7 | AccessorDecl | set |
-| test.swift:104:3:104:3 | AccessorDecl | ? |
-| test.swift:105:5:107:5 | AccessorDecl | get |
-| test.swift:108:5:108:11 | AccessorDecl | set |
-| test.swift:111:37:113:3 | AccessorDecl | get |
-| test.swift:115:7:115:7 | AccessorDecl | ? |
-| test.swift:115:7:115:7 | AccessorDecl | get |
-| test.swift:115:7:115:7 | AccessorDecl | set |
-| test.swift:116:5:116:25 | AccessorDecl | willSet |
-| test.swift:119:7:119:7 | AccessorDecl | ? |
-| test.swift:119:7:119:7 | AccessorDecl | get |
-| test.swift:119:7:119:7 | AccessorDecl | set |
-| test.swift:120:5:120:15 | AccessorDecl | willSet |
-| test.swift:123:7:123:7 | AccessorDecl | ? |
-| test.swift:123:7:123:7 | AccessorDecl | get |
-| test.swift:123:7:123:7 | AccessorDecl | set |
-| test.swift:124:5:124:24 | AccessorDecl | didSet |
-| test.swift:127:7:127:7 | AccessorDecl | ? |
-| test.swift:127:7:127:7 | AccessorDecl | get |
-| test.swift:127:7:127:7 | AccessorDecl | set |
-| test.swift:128:5:128:14 | AccessorDecl | didSet |
-| test.swift:131:7:131:7 | AccessorDecl | ? |
-| test.swift:131:7:131:7 | AccessorDecl | get |
-| test.swift:131:7:131:7 | AccessorDecl | set |
-| test.swift:132:5:132:15 | AccessorDecl | willSet |
-| test.swift:134:5:134:14 | AccessorDecl | didSet |
+| test.swift:2:7:2:7 | (unnamed function decl) | ? |
+| test.swift:2:7:2:7 | get | get |
+| test.swift:2:7:2:7 | set | set |
+| test.swift:3:7:3:7 | (unnamed function decl) | ? |
+| test.swift:4:5:4:24 | get | get |
+| test.swift:5:5:5:38 | set | set |
+| test.swift:9:17:9:17 | (unnamed function decl) | ? |
+| test.swift:9:17:9:17 | get | get |
+| test.swift:9:17:9:17 | set | set |
+| test.swift:23:9:23:9 | (unnamed function decl) | ? |
+| test.swift:23:31:23:31 | get | get |
+| test.swift:23:35:23:35 | set | set |
+| test.swift:24:40:24:40 | get | get |
+| test.swift:32:3:34:3 | get | get |
+| test.swift:35:3:35:18 | set | set |
+| test.swift:41:7:41:7 | (unnamed function decl) | ? |
+| test.swift:41:7:41:7 | get | get |
+| test.swift:41:7:41:7 | set | set |
+| test.swift:70:5:72:5 | get | get |
+| test.swift:77:20:77:20 | get | get |
+| test.swift:82:7:82:7 | (unnamed function decl) | ? |
+| test.swift:83:5:83:11 | set | set |
+| test.swift:84:5:86:5 | get | get |
+| test.swift:91:27:93:3 | get | get |
+| test.swift:97:5:99:5 | get | get |
+| test.swift:102:7:102:7 | (unnamed function decl) | ? |
+| test.swift:102:7:102:7 | get | get |
+| test.swift:102:7:102:7 | set | set |
+| test.swift:104:3:104:3 | (unnamed function decl) | ? |
+| test.swift:105:5:107:5 | get | get |
+| test.swift:108:5:108:11 | set | set |
+| test.swift:111:37:113:3 | get | get |
+| test.swift:115:7:115:7 | (unnamed function decl) | ? |
+| test.swift:115:7:115:7 | get | get |
+| test.swift:115:7:115:7 | set | set |
+| test.swift:116:5:116:25 | willSet | willSet |
+| test.swift:119:7:119:7 | (unnamed function decl) | ? |
+| test.swift:119:7:119:7 | get | get |
+| test.swift:119:7:119:7 | set | set |
+| test.swift:120:5:120:15 | willSet | willSet |
+| test.swift:123:7:123:7 | (unnamed function decl) | ? |
+| test.swift:123:7:123:7 | get | get |
+| test.swift:123:7:123:7 | set | set |
+| test.swift:124:5:124:24 | didSet | didSet |
+| test.swift:127:7:127:7 | (unnamed function decl) | ? |
+| test.swift:127:7:127:7 | get | get |
+| test.swift:127:7:127:7 | set | set |
+| test.swift:128:5:128:14 | didSet | didSet |
+| test.swift:131:7:131:7 | (unnamed function decl) | ? |
+| test.swift:131:7:131:7 | get | get |
+| test.swift:131:7:131:7 | set | set |
+| test.swift:132:5:132:15 | willSet | willSet |
+| test.swift:134:5:134:14 | didSet | didSet |
diff --git a/swift/ql/test/extractor-tests/declarations/all.expected b/swift/ql/test/extractor-tests/declarations/all.expected
index a8e81767731..17398ce97a9 100644
--- a/swift/ql/test/extractor-tests/declarations/all.expected
+++ b/swift/ql/test/extractor-tests/declarations/all.expected
@@ -1,196 +1,196 @@
-| test.swift:1:1:7:1 | StructDecl |
-| test.swift:1:8:1:8 | ConstructorDecl |
-| test.swift:1:8:1:8 | ConstructorDecl |
-| test.swift:1:8:1:8 | ParamDecl |
-| test.swift:2:3:2:11 | PatternBindingDecl |
-| test.swift:2:7:2:7 | AccessorDecl |
-| test.swift:2:7:2:7 | AccessorDecl |
-| test.swift:2:7:2:7 | AccessorDecl |
-| test.swift:2:7:2:7 | ConcreteVarDecl |
-| test.swift:2:7:2:7 | ParamDecl |
-| test.swift:2:7:2:7 | ParamDecl |
-| test.swift:2:7:2:7 | ParamDecl |
-| test.swift:3:3:6:3 | PatternBindingDecl |
-| test.swift:3:7:3:7 | AccessorDecl |
-| test.swift:3:7:3:7 | ConcreteVarDecl |
-| test.swift:4:5:4:5 | ParamDecl |
-| test.swift:4:5:4:24 | AccessorDecl |
-| test.swift:5:5:5:5 | ParamDecl |
-| test.swift:5:5:5:38 | AccessorDecl |
-| test.swift:5:9:5:9 | ParamDecl |
-| test.swift:9:1:9:34 | ClassDecl |
-| test.swift:9:7:9:7 | ConstructorDecl |
-| test.swift:9:7:9:7 | DestructorDecl |
-| test.swift:9:13:9:30 | PatternBindingDecl |
-| test.swift:9:17:9:17 | AccessorDecl |
-| test.swift:9:17:9:17 | AccessorDecl |
-| test.swift:9:17:9:17 | AccessorDecl |
-| test.swift:9:17:9:17 | ConcreteVarDecl |
-| test.swift:9:17:9:17 | ParamDecl |
-| test.swift:9:17:9:17 | ParamDecl |
-| test.swift:9:17:9:17 | ParamDecl |
-| test.swift:11:1:14:1 | EnumDecl |
-| test.swift:12:5:12:18 | EnumCaseDecl |
-| test.swift:12:10:12:10 | EnumElementDecl |
-| test.swift:12:18:12:18 | EnumElementDecl |
-| test.swift:13:5:13:26 | EnumCaseDecl |
-| test.swift:13:10:13:10 | EnumElementDecl |
-| test.swift:13:18:13:18 | EnumElementDecl |
-| test.swift:13:26:13:26 | EnumElementDecl |
-| test.swift:16:1:20:1 | EnumDecl |
-| test.swift:17:5:17:22 | EnumCaseDecl |
-| test.swift:17:10:17:22 | EnumElementDecl |
-| test.swift:17:18:17:18 | ParamDecl |
-| test.swift:18:5:18:21 | EnumCaseDecl |
-| test.swift:18:10:18:21 | EnumElementDecl |
-| test.swift:18:18:18:18 | ParamDecl |
-| test.swift:19:5:19:35 | EnumCaseDecl |
-| test.swift:19:10:19:35 | EnumElementDecl |
-| test.swift:19:16:19:16 | ParamDecl |
-| test.swift:19:21:19:21 | ParamDecl |
-| test.swift:19:29:19:29 | ParamDecl |
-| test.swift:22:1:26:1 | ProtocolDecl |
-| test.swift:23:5:23:39 | PatternBindingDecl |
-| test.swift:23:9:23:9 | AccessorDecl |
-| test.swift:23:9:23:9 | ConcreteVarDecl |
-| test.swift:23:31:23:31 | AccessorDecl |
-| test.swift:23:35:23:35 | AccessorDecl |
-| test.swift:23:35:23:35 | ParamDecl |
-| test.swift:24:5:24:44 | PatternBindingDecl |
-| test.swift:24:9:24:9 | ConcreteVarDecl |
-| test.swift:24:40:24:40 | AccessorDecl |
-| test.swift:25:5:25:22 | ConcreteFuncDecl |
-| test.swift:28:1:28:37 | ConcreteFuncDecl |
-| test.swift:28:17:28:31 | ParamDecl |
-| test.swift:30:1:30:18 | PatternBindingDecl |
-| test.swift:30:1:30:18 | TopLevelCodeDecl |
-| test.swift:30:5:30:5 | ConcreteVarDecl |
-| test.swift:31:1:36:1 | PatternBindingDecl |
-| test.swift:31:1:36:1 | TopLevelCodeDecl |
-| test.swift:31:5:31:5 | ConcreteVarDecl |
-| test.swift:32:3:34:3 | AccessorDecl |
-| test.swift:35:3:35:18 | AccessorDecl |
-| test.swift:35:7:35:7 | ParamDecl |
-| test.swift:38:1:38:33 | TopLevelCodeDecl |
-| test.swift:40:1:53:1 | ClassDecl |
-| test.swift:41:3:41:14 | PatternBindingDecl |
-| test.swift:41:7:41:7 | AccessorDecl |
-| test.swift:41:7:41:7 | AccessorDecl |
-| test.swift:41:7:41:7 | AccessorDecl |
-| test.swift:41:7:41:7 | ConcreteVarDecl |
-| test.swift:41:7:41:7 | ParamDecl |
-| test.swift:41:7:41:7 | ParamDecl |
-| test.swift:41:7:41:7 | ParamDecl |
-| test.swift:42:3:42:3 | ParamDecl |
-| test.swift:42:3:44:3 | ConstructorDecl |
-| test.swift:46:3:46:3 | ParamDecl |
-| test.swift:46:3:48:3 | DestructorDecl |
-| test.swift:50:3:52:3 | ConcreteFuncDecl |
-| test.swift:50:26:50:33 | ParamDecl |
-| test.swift:55:8:55:17 | PrefixOperatorDecl |
-| test.swift:57:1:62:1 | PrecedenceGroupDecl |
-| test.swift:64:7:64:16 | InfixOperatorDecl |
-| test.swift:66:7:66:21 | InfixOperatorDecl |
-| test.swift:68:18:74:1 | StructDecl |
-| test.swift:68:25:68:25 | ConstructorDecl |
-| test.swift:69:3:73:3 | PatternBindingDecl |
-| test.swift:69:7:69:7 | ConcreteVarDecl |
-| test.swift:70:5:72:5 | AccessorDecl |
-| test.swift:76:1:79:1 | ConcreteFuncDecl |
-| test.swift:77:16:77:23 | PatternBindingDecl |
-| test.swift:77:20:77:20 | AccessorDecl |
-| test.swift:77:20:77:20 | ConcreteVarDecl |
-| test.swift:77:20:77:20 | ConcreteVarDecl |
-| test.swift:81:1:136:1 | StructDecl |
-| test.swift:81:8:81:8 | ConstructorDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:81:8:81:8 | ParamDecl |
-| test.swift:82:3:87:3 | PatternBindingDecl |
-| test.swift:82:7:82:7 | AccessorDecl |
-| test.swift:82:7:82:7 | ConcreteVarDecl |
-| test.swift:83:5:83:5 | ParamDecl |
-| test.swift:83:5:83:11 | AccessorDecl |
-| test.swift:84:5:86:5 | AccessorDecl |
-| test.swift:91:3:93:3 | PatternBindingDecl |
-| test.swift:91:7:91:7 | ConcreteVarDecl |
-| test.swift:91:27:93:3 | AccessorDecl |
-| test.swift:96:3:100:3 | PatternBindingDecl |
-| test.swift:96:7:96:7 | ConcreteVarDecl |
-| test.swift:97:5:99:5 | AccessorDecl |
-| test.swift:102:3:102:21 | PatternBindingDecl |
-| test.swift:102:7:102:7 | AccessorDecl |
-| test.swift:102:7:102:7 | AccessorDecl |
-| test.swift:102:7:102:7 | AccessorDecl |
-| test.swift:102:7:102:7 | ConcreteVarDecl |
-| test.swift:102:7:102:7 | ParamDecl |
-| test.swift:102:7:102:7 | ParamDecl |
-| test.swift:102:7:102:7 | ParamDecl |
-| test.swift:104:3:104:3 | AccessorDecl |
-| test.swift:104:3:109:3 | SubscriptDecl |
-| test.swift:104:13:104:13 | ParamDecl |
-| test.swift:104:13:104:13 | ParamDecl |
-| test.swift:104:13:104:16 | ParamDecl |
-| test.swift:105:5:107:5 | AccessorDecl |
-| test.swift:108:5:108:5 | ParamDecl |
-| test.swift:108:5:108:11 | AccessorDecl |
-| test.swift:111:3:113:3 | SubscriptDecl |
-| test.swift:111:13:111:13 | ParamDecl |
-| test.swift:111:13:111:16 | ParamDecl |
-| test.swift:111:21:111:21 | ParamDecl |
-| test.swift:111:21:111:25 | ParamDecl |
-| test.swift:111:37:113:3 | AccessorDecl |
-| test.swift:115:3:117:3 | PatternBindingDecl |
-| test.swift:115:7:115:7 | AccessorDecl |
-| test.swift:115:7:115:7 | AccessorDecl |
-| test.swift:115:7:115:7 | AccessorDecl |
-| test.swift:115:7:115:7 | ConcreteVarDecl |
-| test.swift:115:7:115:7 | ParamDecl |
-| test.swift:115:7:115:7 | ParamDecl |
-| test.swift:115:7:115:7 | ParamDecl |
-| test.swift:116:5:116:25 | AccessorDecl |
-| test.swift:116:13:116:13 | ParamDecl |
-| test.swift:119:3:121:3 | PatternBindingDecl |
-| test.swift:119:7:119:7 | AccessorDecl |
-| test.swift:119:7:119:7 | AccessorDecl |
-| test.swift:119:7:119:7 | AccessorDecl |
-| test.swift:119:7:119:7 | ConcreteVarDecl |
-| test.swift:119:7:119:7 | ParamDecl |
-| test.swift:119:7:119:7 | ParamDecl |
-| test.swift:119:7:119:7 | ParamDecl |
-| test.swift:120:5:120:5 | ParamDecl |
-| test.swift:120:5:120:15 | AccessorDecl |
-| test.swift:123:3:125:3 | PatternBindingDecl |
-| test.swift:123:7:123:7 | AccessorDecl |
-| test.swift:123:7:123:7 | AccessorDecl |
-| test.swift:123:7:123:7 | AccessorDecl |
-| test.swift:123:7:123:7 | ConcreteVarDecl |
-| test.swift:123:7:123:7 | ParamDecl |
-| test.swift:123:7:123:7 | ParamDecl |
-| test.swift:123:7:123:7 | ParamDecl |
-| test.swift:124:5:124:24 | AccessorDecl |
-| test.swift:124:12:124:12 | ParamDecl |
-| test.swift:127:3:129:3 | PatternBindingDecl |
-| test.swift:127:7:127:7 | AccessorDecl |
-| test.swift:127:7:127:7 | AccessorDecl |
-| test.swift:127:7:127:7 | AccessorDecl |
-| test.swift:127:7:127:7 | ConcreteVarDecl |
-| test.swift:127:7:127:7 | ParamDecl |
-| test.swift:127:7:127:7 | ParamDecl |
-| test.swift:127:7:127:7 | ParamDecl |
-| test.swift:127:7:127:7 | ParamDecl |
-| test.swift:128:5:128:14 | AccessorDecl |
-| test.swift:131:3:135:3 | PatternBindingDecl |
-| test.swift:131:7:131:7 | AccessorDecl |
-| test.swift:131:7:131:7 | AccessorDecl |
-| test.swift:131:7:131:7 | AccessorDecl |
-| test.swift:131:7:131:7 | ConcreteVarDecl |
-| test.swift:131:7:131:7 | ParamDecl |
-| test.swift:131:7:131:7 | ParamDecl |
-| test.swift:131:7:131:7 | ParamDecl |
-| test.swift:132:5:132:5 | ParamDecl |
-| test.swift:132:5:132:15 | AccessorDecl |
-| test.swift:134:5:134:14 | AccessorDecl |
+| test.swift:1:1:7:1 | Foo |
+| test.swift:1:8:1:8 | deinit |
+| test.swift:1:8:1:8 | deinit |
+| test.swift:1:8:1:8 | x |
+| test.swift:2:3:2:11 | var ... = ... |
+| test.swift:2:7:2:7 | (unnamed function decl) |
+| test.swift:2:7:2:7 | get |
+| test.swift:2:7:2:7 | self |
+| test.swift:2:7:2:7 | self |
+| test.swift:2:7:2:7 | set |
+| test.swift:2:7:2:7 | value |
+| test.swift:2:7:2:7 | x |
+| test.swift:3:3:6:3 | var ... = ... |
+| test.swift:3:7:3:7 | (unnamed function decl) |
+| test.swift:3:7:3:7 | next |
+| test.swift:4:5:4:5 | self |
+| test.swift:4:5:4:24 | get |
+| test.swift:5:5:5:5 | self |
+| test.swift:5:5:5:38 | set |
+| test.swift:5:9:5:9 | newValue |
+| test.swift:9:1:9:34 | Bar |
+| test.swift:9:7:9:7 | deinit |
+| test.swift:9:7:9:7 | init |
+| test.swift:9:13:9:30 | var ... = ... |
+| test.swift:9:17:9:17 | (unnamed function decl) |
+| test.swift:9:17:9:17 | get |
+| test.swift:9:17:9:17 | self |
+| test.swift:9:17:9:17 | self |
+| test.swift:9:17:9:17 | set |
+| test.swift:9:17:9:17 | value |
+| test.swift:9:17:9:17 | x |
+| test.swift:11:1:14:1 | EnumValues |
+| test.swift:12:5:12:18 | case ... |
+| test.swift:12:10:12:10 | value1 |
+| test.swift:12:18:12:18 | value2 |
+| test.swift:13:5:13:26 | case ... |
+| test.swift:13:10:13:10 | value3 |
+| test.swift:13:18:13:18 | value4 |
+| test.swift:13:26:13:26 | value5 |
+| test.swift:16:1:20:1 | EnumWithParams |
+| test.swift:17:5:17:22 | case ... |
+| test.swift:17:10:17:22 | nodata1 |
+| test.swift:17:18:17:18 | _ |
+| test.swift:18:5:18:21 | case ... |
+| test.swift:18:10:18:21 | intdata |
+| test.swift:18:18:18:18 | _ |
+| test.swift:19:5:19:35 | case ... |
+| test.swift:19:10:19:35 | tuple |
+| test.swift:19:16:19:16 | _ |
+| test.swift:19:21:19:21 | _ |
+| test.swift:19:29:19:29 | _ |
+| test.swift:22:1:26:1 | MyProtocol |
+| test.swift:23:5:23:39 | var ... = ... |
+| test.swift:23:9:23:9 | (unnamed function decl) |
+| test.swift:23:9:23:9 | mustBeSettable |
+| test.swift:23:31:23:31 | get |
+| test.swift:23:35:23:35 | newValue |
+| test.swift:23:35:23:35 | set |
+| test.swift:24:5:24:44 | var ... = ... |
+| test.swift:24:9:24:9 | doesNotNeedToBeSettable |
+| test.swift:24:40:24:40 | get |
+| test.swift:25:5:25:22 | random |
+| test.swift:28:1:28:37 | a_function |
+| test.swift:28:17:28:31 | a_parameter |
+| test.swift:30:1:30:18 | var ... = ... |
+| test.swift:30:1:30:18 | { ... } |
+| test.swift:30:5:30:5 | a_variable |
+| test.swift:31:1:36:1 | var ... = ... |
+| test.swift:31:1:36:1 | { ... } |
+| test.swift:31:5:31:5 | a_property |
+| test.swift:32:3:34:3 | get |
+| test.swift:35:3:35:18 | set |
+| test.swift:35:7:35:7 | newValue |
+| test.swift:38:1:38:33 | { ... } |
+| test.swift:40:1:53:1 | Baz |
+| test.swift:41:3:41:14 | var ... = ... |
+| test.swift:41:7:41:7 | (unnamed function decl) |
+| test.swift:41:7:41:7 | field |
+| test.swift:41:7:41:7 | get |
+| test.swift:41:7:41:7 | self |
+| test.swift:41:7:41:7 | self |
+| test.swift:41:7:41:7 | set |
+| test.swift:41:7:41:7 | value |
+| test.swift:42:3:42:3 | self |
+| test.swift:42:3:44:3 | deinit |
+| test.swift:46:3:46:3 | self |
+| test.swift:46:3:48:3 | init |
+| test.swift:50:3:52:3 | +- |
+| test.swift:50:26:50:33 | other |
+| test.swift:55:8:55:17 | +- |
+| test.swift:57:1:62:1 | precedencegroup ... |
+| test.swift:64:7:64:16 | +++ |
+| test.swift:66:7:66:21 | *** |
+| test.swift:68:18:74:1 | ZeroWrapper |
+| test.swift:68:25:68:25 | deinit |
+| test.swift:69:3:73:3 | var ... = ... |
+| test.swift:69:7:69:7 | wrappedValue |
+| test.swift:70:5:72:5 | get |
+| test.swift:76:1:79:1 | foo |
+| test.swift:77:16:77:23 | var ... = ... |
+| test.swift:77:20:77:20 | _x |
+| test.swift:77:20:77:20 | get |
+| test.swift:77:20:77:20 | x |
+| test.swift:81:1:136:1 | HasPropertyAndObserver |
+| test.swift:81:8:81:8 | deinit |
+| test.swift:81:8:81:8 | hasBoth |
+| test.swift:81:8:81:8 | hasDidSet1 |
+| test.swift:81:8:81:8 | hasDidSet2 |
+| test.swift:81:8:81:8 | hasWillSet1 |
+| test.swift:81:8:81:8 | hasWillSet2 |
+| test.swift:81:8:81:8 | normalField |
+| test.swift:82:3:87:3 | var ... = ... |
+| test.swift:82:7:82:7 | (unnamed function decl) |
+| test.swift:82:7:82:7 | settableField |
+| test.swift:83:5:83:5 | newValue |
+| test.swift:83:5:83:11 | set |
+| test.swift:84:5:86:5 | get |
+| test.swift:91:3:93:3 | var ... = ... |
+| test.swift:91:7:91:7 | readOnlyField1 |
+| test.swift:91:27:93:3 | get |
+| test.swift:96:3:100:3 | var ... = ... |
+| test.swift:96:7:96:7 | readOnlyField2 |
+| test.swift:97:5:99:5 | get |
+| test.swift:102:3:102:21 | var ... = ... |
+| test.swift:102:7:102:7 | (unnamed function decl) |
+| test.swift:102:7:102:7 | get |
+| test.swift:102:7:102:7 | normalField |
+| test.swift:102:7:102:7 | self |
+| test.swift:102:7:102:7 | self |
+| test.swift:102:7:102:7 | set |
+| test.swift:102:7:102:7 | value |
+| test.swift:104:3:104:3 | (unnamed function decl) |
+| test.swift:104:3:109:3 | subscript ... |
+| test.swift:104:13:104:13 | x |
+| test.swift:104:13:104:13 | x |
+| test.swift:104:13:104:16 | x |
+| test.swift:105:5:107:5 | get |
+| test.swift:108:5:108:5 | newValue |
+| test.swift:108:5:108:11 | set |
+| test.swift:111:3:113:3 | subscript ... |
+| test.swift:111:13:111:13 | x |
+| test.swift:111:13:111:16 | x |
+| test.swift:111:21:111:21 | y |
+| test.swift:111:21:111:25 | y |
+| test.swift:111:37:113:3 | get |
+| test.swift:115:3:117:3 | var ... = ... |
+| test.swift:115:7:115:7 | (unnamed function decl) |
+| test.swift:115:7:115:7 | get |
+| test.swift:115:7:115:7 | hasWillSet1 |
+| test.swift:115:7:115:7 | self |
+| test.swift:115:7:115:7 | self |
+| test.swift:115:7:115:7 | set |
+| test.swift:115:7:115:7 | value |
+| test.swift:116:5:116:25 | willSet |
+| test.swift:116:13:116:13 | newValue |
+| test.swift:119:3:121:3 | var ... = ... |
+| test.swift:119:7:119:7 | (unnamed function decl) |
+| test.swift:119:7:119:7 | get |
+| test.swift:119:7:119:7 | hasWillSet2 |
+| test.swift:119:7:119:7 | self |
+| test.swift:119:7:119:7 | self |
+| test.swift:119:7:119:7 | set |
+| test.swift:119:7:119:7 | value |
+| test.swift:120:5:120:5 | newValue |
+| test.swift:120:5:120:15 | willSet |
+| test.swift:123:3:125:3 | var ... = ... |
+| test.swift:123:7:123:7 | (unnamed function decl) |
+| test.swift:123:7:123:7 | get |
+| test.swift:123:7:123:7 | hasDidSet1 |
+| test.swift:123:7:123:7 | self |
+| test.swift:123:7:123:7 | self |
+| test.swift:123:7:123:7 | set |
+| test.swift:123:7:123:7 | value |
+| test.swift:124:5:124:24 | didSet |
+| test.swift:124:12:124:12 | oldValue |
+| test.swift:127:3:129:3 | var ... = ... |
+| test.swift:127:7:127:7 | (unnamed function decl) |
+| test.swift:127:7:127:7 | get |
+| test.swift:127:7:127:7 | hasDidSet2 |
+| test.swift:127:7:127:7 | self |
+| test.swift:127:7:127:7 | self |
+| test.swift:127:7:127:7 | self |
+| test.swift:127:7:127:7 | set |
+| test.swift:127:7:127:7 | value |
+| test.swift:128:5:128:14 | didSet |
+| test.swift:131:3:135:3 | var ... = ... |
+| test.swift:131:7:131:7 | (unnamed function decl) |
+| test.swift:131:7:131:7 | get |
+| test.swift:131:7:131:7 | hasBoth |
+| test.swift:131:7:131:7 | self |
+| test.swift:131:7:131:7 | self |
+| test.swift:131:7:131:7 | set |
+| test.swift:131:7:131:7 | value |
+| test.swift:132:5:132:5 | newValue |
+| test.swift:132:5:132:15 | willSet |
+| test.swift:134:5:134:14 | didSet |
diff --git a/swift/ql/test/extractor-tests/declarations/func.expected b/swift/ql/test/extractor-tests/declarations/func.expected
index b96781829d3..5eb8c4e6f30 100644
--- a/swift/ql/test/extractor-tests/declarations/func.expected
+++ b/swift/ql/test/extractor-tests/declarations/func.expected
@@ -1,57 +1,57 @@
-| test.swift:2:7:2:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:2:7:2:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:2:7:2:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:3:7:3:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:4:5:4:24 | AccessorDecl | (unnamed function decl) |
-| test.swift:5:5:5:38 | AccessorDecl | (unnamed function decl) |
-| test.swift:9:17:9:17 | AccessorDecl | (unnamed function decl) |
-| test.swift:9:17:9:17 | AccessorDecl | (unnamed function decl) |
-| test.swift:9:17:9:17 | AccessorDecl | (unnamed function decl) |
-| test.swift:23:9:23:9 | AccessorDecl | (unnamed function decl) |
-| test.swift:23:31:23:31 | AccessorDecl | (unnamed function decl) |
-| test.swift:23:35:23:35 | AccessorDecl | (unnamed function decl) |
-| test.swift:24:40:24:40 | AccessorDecl | (unnamed function decl) |
-| test.swift:25:5:25:22 | ConcreteFuncDecl | random |
-| test.swift:28:1:28:37 | ConcreteFuncDecl | a_function |
-| test.swift:32:3:34:3 | AccessorDecl | (unnamed function decl) |
-| test.swift:35:3:35:18 | AccessorDecl | (unnamed function decl) |
-| test.swift:41:7:41:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:41:7:41:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:41:7:41:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:50:3:52:3 | ConcreteFuncDecl | +- |
-| test.swift:70:5:72:5 | AccessorDecl | (unnamed function decl) |
-| test.swift:76:1:79:1 | ConcreteFuncDecl | foo |
-| test.swift:77:20:77:20 | AccessorDecl | (unnamed function decl) |
-| test.swift:82:7:82:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:83:5:83:11 | AccessorDecl | (unnamed function decl) |
-| test.swift:84:5:86:5 | AccessorDecl | (unnamed function decl) |
-| test.swift:91:27:93:3 | AccessorDecl | (unnamed function decl) |
-| test.swift:97:5:99:5 | AccessorDecl | (unnamed function decl) |
-| test.swift:102:7:102:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:102:7:102:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:102:7:102:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:104:3:104:3 | AccessorDecl | (unnamed function decl) |
-| test.swift:105:5:107:5 | AccessorDecl | (unnamed function decl) |
-| test.swift:108:5:108:11 | AccessorDecl | (unnamed function decl) |
-| test.swift:111:37:113:3 | AccessorDecl | (unnamed function decl) |
-| test.swift:115:7:115:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:115:7:115:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:115:7:115:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:116:5:116:25 | AccessorDecl | (unnamed function decl) |
-| test.swift:119:7:119:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:119:7:119:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:119:7:119:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:120:5:120:15 | AccessorDecl | (unnamed function decl) |
-| test.swift:123:7:123:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:123:7:123:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:123:7:123:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:124:5:124:24 | AccessorDecl | (unnamed function decl) |
-| test.swift:127:7:127:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:127:7:127:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:127:7:127:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:128:5:128:14 | AccessorDecl | (unnamed function decl) |
-| test.swift:131:7:131:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:131:7:131:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:131:7:131:7 | AccessorDecl | (unnamed function decl) |
-| test.swift:132:5:132:15 | AccessorDecl | (unnamed function decl) |
-| test.swift:134:5:134:14 | AccessorDecl | (unnamed function decl) |
+| test.swift:2:7:2:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:2:7:2:7 | get | (unnamed function decl) |
+| test.swift:2:7:2:7 | set | (unnamed function decl) |
+| test.swift:3:7:3:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:4:5:4:24 | get | (unnamed function decl) |
+| test.swift:5:5:5:38 | set | (unnamed function decl) |
+| test.swift:9:17:9:17 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:9:17:9:17 | get | (unnamed function decl) |
+| test.swift:9:17:9:17 | set | (unnamed function decl) |
+| test.swift:23:9:23:9 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:23:31:23:31 | get | (unnamed function decl) |
+| test.swift:23:35:23:35 | set | (unnamed function decl) |
+| test.swift:24:40:24:40 | get | (unnamed function decl) |
+| test.swift:25:5:25:22 | random | random |
+| test.swift:28:1:28:37 | a_function | a_function |
+| test.swift:32:3:34:3 | get | (unnamed function decl) |
+| test.swift:35:3:35:18 | set | (unnamed function decl) |
+| test.swift:41:7:41:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:41:7:41:7 | get | (unnamed function decl) |
+| test.swift:41:7:41:7 | set | (unnamed function decl) |
+| test.swift:50:3:52:3 | +- | +- |
+| test.swift:70:5:72:5 | get | (unnamed function decl) |
+| test.swift:76:1:79:1 | foo | foo |
+| test.swift:77:20:77:20 | get | (unnamed function decl) |
+| test.swift:82:7:82:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:83:5:83:11 | set | (unnamed function decl) |
+| test.swift:84:5:86:5 | get | (unnamed function decl) |
+| test.swift:91:27:93:3 | get | (unnamed function decl) |
+| test.swift:97:5:99:5 | get | (unnamed function decl) |
+| test.swift:102:7:102:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:102:7:102:7 | get | (unnamed function decl) |
+| test.swift:102:7:102:7 | set | (unnamed function decl) |
+| test.swift:104:3:104:3 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:105:5:107:5 | get | (unnamed function decl) |
+| test.swift:108:5:108:11 | set | (unnamed function decl) |
+| test.swift:111:37:113:3 | get | (unnamed function decl) |
+| test.swift:115:7:115:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:115:7:115:7 | get | (unnamed function decl) |
+| test.swift:115:7:115:7 | set | (unnamed function decl) |
+| test.swift:116:5:116:25 | willSet | (unnamed function decl) |
+| test.swift:119:7:119:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:119:7:119:7 | get | (unnamed function decl) |
+| test.swift:119:7:119:7 | set | (unnamed function decl) |
+| test.swift:120:5:120:15 | willSet | (unnamed function decl) |
+| test.swift:123:7:123:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:123:7:123:7 | get | (unnamed function decl) |
+| test.swift:123:7:123:7 | set | (unnamed function decl) |
+| test.swift:124:5:124:24 | didSet | (unnamed function decl) |
+| test.swift:127:7:127:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:127:7:127:7 | get | (unnamed function decl) |
+| test.swift:127:7:127:7 | set | (unnamed function decl) |
+| test.swift:128:5:128:14 | didSet | (unnamed function decl) |
+| test.swift:131:7:131:7 | (unnamed function decl) | (unnamed function decl) |
+| test.swift:131:7:131:7 | get | (unnamed function decl) |
+| test.swift:131:7:131:7 | set | (unnamed function decl) |
+| test.swift:132:5:132:15 | willSet | (unnamed function decl) |
+| test.swift:134:5:134:14 | didSet | (unnamed function decl) |
diff --git a/swift/ql/test/extractor-tests/declarations/func_body.expected b/swift/ql/test/extractor-tests/declarations/func_body.expected
index 02ddacad327..15652c1b37c 100644
--- a/swift/ql/test/extractor-tests/declarations/func_body.expected
+++ b/swift/ql/test/extractor-tests/declarations/func_body.expected
@@ -1,52 +1,52 @@
-| test.swift:2:7:2:7 | AccessorDecl | test.swift:2:7:2:7 | BraceStmt |
-| test.swift:2:7:2:7 | AccessorDecl | test.swift:2:7:2:7 | BraceStmt |
-| test.swift:2:7:2:7 | AccessorDecl | test.swift:2:7:2:7 | BraceStmt |
-| test.swift:3:7:3:7 | AccessorDecl | test.swift:3:7:3:7 | BraceStmt |
-| test.swift:4:5:4:24 | AccessorDecl | test.swift:4:9:4:24 | BraceStmt |
-| test.swift:5:5:5:38 | AccessorDecl | test.swift:5:19:5:38 | BraceStmt |
-| test.swift:9:17:9:17 | AccessorDecl | test.swift:9:17:9:17 | BraceStmt |
-| test.swift:9:17:9:17 | AccessorDecl | test.swift:9:17:9:17 | BraceStmt |
-| test.swift:9:17:9:17 | AccessorDecl | test.swift:9:17:9:17 | BraceStmt |
-| test.swift:28:1:28:37 | ConcreteFuncDecl | test.swift:28:36:28:37 | BraceStmt |
-| test.swift:32:3:34:3 | AccessorDecl | test.swift:32:7:34:3 | BraceStmt |
-| test.swift:35:3:35:18 | AccessorDecl | test.swift:35:17:35:18 | BraceStmt |
-| test.swift:41:7:41:7 | AccessorDecl | test.swift:41:7:41:7 | BraceStmt |
-| test.swift:41:7:41:7 | AccessorDecl | test.swift:41:7:41:7 | BraceStmt |
-| test.swift:41:7:41:7 | AccessorDecl | test.swift:41:7:41:7 | BraceStmt |
-| test.swift:50:3:52:3 | ConcreteFuncDecl | test.swift:50:45:52:3 | BraceStmt |
-| test.swift:70:5:72:5 | AccessorDecl | test.swift:70:9:72:5 | BraceStmt |
-| test.swift:76:1:79:1 | ConcreteFuncDecl | test.swift:76:19:79:1 | BraceStmt |
-| test.swift:77:20:77:20 | AccessorDecl | test.swift:77:20:77:20 | BraceStmt |
-| test.swift:82:7:82:7 | AccessorDecl | test.swift:82:7:82:7 | BraceStmt |
-| test.swift:83:5:83:11 | AccessorDecl | test.swift:83:9:83:11 | BraceStmt |
-| test.swift:84:5:86:5 | AccessorDecl | test.swift:84:9:86:5 | BraceStmt |
-| test.swift:91:27:93:3 | AccessorDecl | test.swift:91:27:93:3 | BraceStmt |
-| test.swift:97:5:99:5 | AccessorDecl | test.swift:97:9:99:5 | BraceStmt |
-| test.swift:102:7:102:7 | AccessorDecl | test.swift:102:7:102:7 | BraceStmt |
-| test.swift:102:7:102:7 | AccessorDecl | test.swift:102:7:102:7 | BraceStmt |
-| test.swift:102:7:102:7 | AccessorDecl | test.swift:102:7:102:7 | BraceStmt |
-| test.swift:104:3:104:3 | AccessorDecl | test.swift:104:3:104:3 | BraceStmt |
-| test.swift:105:5:107:5 | AccessorDecl | test.swift:105:9:107:5 | BraceStmt |
-| test.swift:108:5:108:11 | AccessorDecl | test.swift:108:9:108:11 | BraceStmt |
-| test.swift:111:37:113:3 | AccessorDecl | test.swift:111:37:113:3 | BraceStmt |
-| test.swift:115:7:115:7 | AccessorDecl | test.swift:115:7:115:7 | BraceStmt |
-| test.swift:115:7:115:7 | AccessorDecl | test.swift:115:7:115:7 | BraceStmt |
-| test.swift:115:7:115:7 | AccessorDecl | test.swift:115:7:115:7 | BraceStmt |
-| test.swift:116:5:116:25 | AccessorDecl | test.swift:116:23:116:25 | BraceStmt |
-| test.swift:119:7:119:7 | AccessorDecl | test.swift:119:7:119:7 | BraceStmt |
-| test.swift:119:7:119:7 | AccessorDecl | test.swift:119:7:119:7 | BraceStmt |
-| test.swift:119:7:119:7 | AccessorDecl | test.swift:119:7:119:7 | BraceStmt |
-| test.swift:120:5:120:15 | AccessorDecl | test.swift:120:13:120:15 | BraceStmt |
-| test.swift:123:7:123:7 | AccessorDecl | test.swift:123:7:123:7 | BraceStmt |
-| test.swift:123:7:123:7 | AccessorDecl | test.swift:123:7:123:7 | BraceStmt |
-| test.swift:123:7:123:7 | AccessorDecl | test.swift:123:7:123:7 | BraceStmt |
-| test.swift:124:5:124:24 | AccessorDecl | test.swift:124:22:124:24 | BraceStmt |
-| test.swift:127:7:127:7 | AccessorDecl | test.swift:127:7:127:7 | BraceStmt |
-| test.swift:127:7:127:7 | AccessorDecl | test.swift:127:7:127:7 | BraceStmt |
-| test.swift:127:7:127:7 | AccessorDecl | test.swift:127:7:127:7 | BraceStmt |
-| test.swift:128:5:128:14 | AccessorDecl | test.swift:128:12:128:14 | BraceStmt |
-| test.swift:131:7:131:7 | AccessorDecl | test.swift:131:7:131:7 | BraceStmt |
-| test.swift:131:7:131:7 | AccessorDecl | test.swift:131:7:131:7 | BraceStmt |
-| test.swift:131:7:131:7 | AccessorDecl | test.swift:131:7:131:7 | BraceStmt |
-| test.swift:132:5:132:15 | AccessorDecl | test.swift:132:13:132:15 | BraceStmt |
-| test.swift:134:5:134:14 | AccessorDecl | test.swift:134:12:134:14 | BraceStmt |
+| test.swift:2:7:2:7 | (unnamed function decl) | test.swift:2:7:2:7 | { ... } |
+| test.swift:2:7:2:7 | get | test.swift:2:7:2:7 | { ... } |
+| test.swift:2:7:2:7 | set | test.swift:2:7:2:7 | { ... } |
+| test.swift:3:7:3:7 | (unnamed function decl) | test.swift:3:7:3:7 | { ... } |
+| test.swift:4:5:4:24 | get | test.swift:4:9:4:24 | { ... } |
+| test.swift:5:5:5:38 | set | test.swift:5:19:5:38 | { ... } |
+| test.swift:9:17:9:17 | (unnamed function decl) | test.swift:9:17:9:17 | { ... } |
+| test.swift:9:17:9:17 | get | test.swift:9:17:9:17 | { ... } |
+| test.swift:9:17:9:17 | set | test.swift:9:17:9:17 | { ... } |
+| test.swift:28:1:28:37 | a_function | test.swift:28:36:28:37 | { ... } |
+| test.swift:32:3:34:3 | get | test.swift:32:7:34:3 | { ... } |
+| test.swift:35:3:35:18 | set | test.swift:35:17:35:18 | { ... } |
+| test.swift:41:7:41:7 | (unnamed function decl) | test.swift:41:7:41:7 | { ... } |
+| test.swift:41:7:41:7 | get | test.swift:41:7:41:7 | { ... } |
+| test.swift:41:7:41:7 | set | test.swift:41:7:41:7 | { ... } |
+| test.swift:50:3:52:3 | +- | test.swift:50:45:52:3 | { ... } |
+| test.swift:70:5:72:5 | get | test.swift:70:9:72:5 | { ... } |
+| test.swift:76:1:79:1 | foo | test.swift:76:19:79:1 | { ... } |
+| test.swift:77:20:77:20 | get | test.swift:77:20:77:20 | { ... } |
+| test.swift:82:7:82:7 | (unnamed function decl) | test.swift:82:7:82:7 | { ... } |
+| test.swift:83:5:83:11 | set | test.swift:83:9:83:11 | { ... } |
+| test.swift:84:5:86:5 | get | test.swift:84:9:86:5 | { ... } |
+| test.swift:91:27:93:3 | get | test.swift:91:27:93:3 | { ... } |
+| test.swift:97:5:99:5 | get | test.swift:97:9:99:5 | { ... } |
+| test.swift:102:7:102:7 | (unnamed function decl) | test.swift:102:7:102:7 | { ... } |
+| test.swift:102:7:102:7 | get | test.swift:102:7:102:7 | { ... } |
+| test.swift:102:7:102:7 | set | test.swift:102:7:102:7 | { ... } |
+| test.swift:104:3:104:3 | (unnamed function decl) | test.swift:104:3:104:3 | { ... } |
+| test.swift:105:5:107:5 | get | test.swift:105:9:107:5 | { ... } |
+| test.swift:108:5:108:11 | set | test.swift:108:9:108:11 | { ... } |
+| test.swift:111:37:113:3 | get | test.swift:111:37:113:3 | { ... } |
+| test.swift:115:7:115:7 | (unnamed function decl) | test.swift:115:7:115:7 | { ... } |
+| test.swift:115:7:115:7 | get | test.swift:115:7:115:7 | { ... } |
+| test.swift:115:7:115:7 | set | test.swift:115:7:115:7 | { ... } |
+| test.swift:116:5:116:25 | willSet | test.swift:116:23:116:25 | { ... } |
+| test.swift:119:7:119:7 | (unnamed function decl) | test.swift:119:7:119:7 | { ... } |
+| test.swift:119:7:119:7 | get | test.swift:119:7:119:7 | { ... } |
+| test.swift:119:7:119:7 | set | test.swift:119:7:119:7 | { ... } |
+| test.swift:120:5:120:15 | willSet | test.swift:120:13:120:15 | { ... } |
+| test.swift:123:7:123:7 | (unnamed function decl) | test.swift:123:7:123:7 | { ... } |
+| test.swift:123:7:123:7 | get | test.swift:123:7:123:7 | { ... } |
+| test.swift:123:7:123:7 | set | test.swift:123:7:123:7 | { ... } |
+| test.swift:124:5:124:24 | didSet | test.swift:124:22:124:24 | { ... } |
+| test.swift:127:7:127:7 | (unnamed function decl) | test.swift:127:7:127:7 | { ... } |
+| test.swift:127:7:127:7 | get | test.swift:127:7:127:7 | { ... } |
+| test.swift:127:7:127:7 | set | test.swift:127:7:127:7 | { ... } |
+| test.swift:128:5:128:14 | didSet | test.swift:128:12:128:14 | { ... } |
+| test.swift:131:7:131:7 | (unnamed function decl) | test.swift:131:7:131:7 | { ... } |
+| test.swift:131:7:131:7 | get | test.swift:131:7:131:7 | { ... } |
+| test.swift:131:7:131:7 | set | test.swift:131:7:131:7 | { ... } |
+| test.swift:132:5:132:15 | willSet | test.swift:132:13:132:15 | { ... } |
+| test.swift:134:5:134:14 | didSet | test.swift:134:12:134:14 | { ... } |
diff --git a/swift/ql/test/extractor-tests/declarations/func_params.expected b/swift/ql/test/extractor-tests/declarations/func_params.expected
index b490c20ceed..aa94a212e37 100644
--- a/swift/ql/test/extractor-tests/declarations/func_params.expected
+++ b/swift/ql/test/extractor-tests/declarations/func_params.expected
@@ -1,25 +1,25 @@
-| test.swift:2:7:2:7 | AccessorDecl | 0 | test.swift:2:7:2:7 | ParamDecl |
-| test.swift:5:5:5:38 | AccessorDecl | 0 | test.swift:5:9:5:9 | ParamDecl |
-| test.swift:9:17:9:17 | AccessorDecl | 0 | test.swift:9:17:9:17 | ParamDecl |
-| test.swift:23:35:23:35 | AccessorDecl | 0 | test.swift:23:35:23:35 | ParamDecl |
-| test.swift:28:1:28:37 | ConcreteFuncDecl | 0 | test.swift:28:17:28:31 | ParamDecl |
-| test.swift:35:3:35:18 | AccessorDecl | 0 | test.swift:35:7:35:7 | ParamDecl |
-| test.swift:41:7:41:7 | AccessorDecl | 0 | test.swift:41:7:41:7 | ParamDecl |
-| test.swift:50:3:52:3 | ConcreteFuncDecl | 0 | test.swift:50:26:50:33 | ParamDecl |
-| test.swift:83:5:83:11 | AccessorDecl | 0 | test.swift:83:5:83:5 | ParamDecl |
-| test.swift:102:7:102:7 | AccessorDecl | 0 | test.swift:102:7:102:7 | ParamDecl |
-| test.swift:104:3:104:3 | AccessorDecl | 0 | file://:0:0:0:0 | ParamDecl |
-| test.swift:105:5:107:5 | AccessorDecl | 0 | test.swift:104:13:104:13 | ParamDecl |
-| test.swift:108:5:108:11 | AccessorDecl | 0 | test.swift:108:5:108:5 | ParamDecl |
-| test.swift:108:5:108:11 | AccessorDecl | 1 | test.swift:104:13:104:13 | ParamDecl |
-| test.swift:111:37:113:3 | AccessorDecl | 0 | test.swift:111:13:111:13 | ParamDecl |
-| test.swift:111:37:113:3 | AccessorDecl | 1 | test.swift:111:21:111:21 | ParamDecl |
-| test.swift:115:7:115:7 | AccessorDecl | 0 | test.swift:115:7:115:7 | ParamDecl |
-| test.swift:116:5:116:25 | AccessorDecl | 0 | test.swift:116:13:116:13 | ParamDecl |
-| test.swift:119:7:119:7 | AccessorDecl | 0 | test.swift:119:7:119:7 | ParamDecl |
-| test.swift:120:5:120:15 | AccessorDecl | 0 | test.swift:120:5:120:5 | ParamDecl |
-| test.swift:123:7:123:7 | AccessorDecl | 0 | test.swift:123:7:123:7 | ParamDecl |
-| test.swift:124:5:124:24 | AccessorDecl | 0 | test.swift:124:12:124:12 | ParamDecl |
-| test.swift:127:7:127:7 | AccessorDecl | 0 | test.swift:127:7:127:7 | ParamDecl |
-| test.swift:131:7:131:7 | AccessorDecl | 0 | test.swift:131:7:131:7 | ParamDecl |
-| test.swift:132:5:132:15 | AccessorDecl | 0 | test.swift:132:5:132:5 | ParamDecl |
+| test.swift:2:7:2:7 | set | 0 | test.swift:2:7:2:7 | value |
+| test.swift:5:5:5:38 | set | 0 | test.swift:5:9:5:9 | newValue |
+| test.swift:9:17:9:17 | set | 0 | test.swift:9:17:9:17 | value |
+| test.swift:23:35:23:35 | set | 0 | test.swift:23:35:23:35 | newValue |
+| test.swift:28:1:28:37 | a_function | 0 | test.swift:28:17:28:31 | a_parameter |
+| test.swift:35:3:35:18 | set | 0 | test.swift:35:7:35:7 | newValue |
+| test.swift:41:7:41:7 | set | 0 | test.swift:41:7:41:7 | value |
+| test.swift:50:3:52:3 | +- | 0 | test.swift:50:26:50:33 | other |
+| test.swift:83:5:83:11 | set | 0 | test.swift:83:5:83:5 | newValue |
+| test.swift:102:7:102:7 | set | 0 | test.swift:102:7:102:7 | value |
+| test.swift:104:3:104:3 | (unnamed function decl) | 0 | file://:0:0:0:0 | x |
+| test.swift:105:5:107:5 | get | 0 | test.swift:104:13:104:13 | x |
+| test.swift:108:5:108:11 | set | 0 | test.swift:108:5:108:5 | newValue |
+| test.swift:108:5:108:11 | set | 1 | test.swift:104:13:104:13 | x |
+| test.swift:111:37:113:3 | get | 0 | test.swift:111:13:111:13 | x |
+| test.swift:111:37:113:3 | get | 1 | test.swift:111:21:111:21 | y |
+| test.swift:115:7:115:7 | set | 0 | test.swift:115:7:115:7 | value |
+| test.swift:116:5:116:25 | willSet | 0 | test.swift:116:13:116:13 | newValue |
+| test.swift:119:7:119:7 | set | 0 | test.swift:119:7:119:7 | value |
+| test.swift:120:5:120:15 | willSet | 0 | test.swift:120:5:120:5 | newValue |
+| test.swift:123:7:123:7 | set | 0 | test.swift:123:7:123:7 | value |
+| test.swift:124:5:124:24 | didSet | 0 | test.swift:124:12:124:12 | oldValue |
+| test.swift:127:7:127:7 | set | 0 | test.swift:127:7:127:7 | value |
+| test.swift:131:7:131:7 | set | 0 | test.swift:131:7:131:7 | value |
+| test.swift:132:5:132:15 | willSet | 0 | test.swift:132:5:132:5 | newValue |
diff --git a/swift/ql/test/extractor-tests/expressions/all.expected b/swift/ql/test/extractor-tests/expressions/all.expected
index 59aab6efe71..d8094e7f54f 100644
--- a/swift/ql/test/extractor-tests/expressions/all.expected
+++ b/swift/ql/test/extractor-tests/expressions/all.expected
@@ -1,231 +1,234 @@
-| expressions.swift:1:9:1:9 | IntegerLiteralExpr |
-| expressions.swift:2:9:2:9 | FloatLiteralExpr |
-| expressions.swift:3:10:3:10 | BooleanLiteralExpr |
-| expressions.swift:4:10:4:10 | BooleanLiteralExpr |
-| expressions.swift:5:9:5:9 | MagicIdentifierLiteralExpr |
-| expressions.swift:6:9:6:9 | StringLiteralExpr |
-| expressions.swift:7:10:7:10 | InterpolatedStringLiteralExpr |
+| expressions.swift:1:9:1:9 | 15 |
+| expressions.swift:2:9:2:9 | 15.15 |
+| expressions.swift:3:10:3:10 | true |
+| expressions.swift:4:10:4:10 | false |
+| expressions.swift:5:9:5:9 | #... |
+| expressions.swift:6:9:6:9 | hello world |
+| expressions.swift:7:10:7:10 | "..." |
| expressions.swift:7:10:7:10 | OpaqueValueExpr |
-| expressions.swift:7:10:7:10 | StringLiteralExpr |
| expressions.swift:7:10:7:10 | TapExpr |
-| expressions.swift:7:11:7:10 | CallExpr |
-| expressions.swift:7:11:7:11 | DeclRefExpr |
-| expressions.swift:7:11:7:11 | DotSyntaxCallExpr |
-| expressions.swift:7:11:7:11 | InOutExpr |
-| expressions.swift:7:18:7:18 | DeclRefExpr |
-| expressions.swift:7:18:7:18 | DeclRefExpr |
-| expressions.swift:7:18:7:18 | DotSyntaxCallExpr |
-| expressions.swift:7:18:7:18 | InOutExpr |
-| expressions.swift:7:18:7:20 | CallExpr |
-| expressions.swift:7:19:7:19 | DeclRefExpr |
-| expressions.swift:7:21:7:21 | CallExpr |
-| expressions.swift:7:21:7:21 | DeclRefExpr |
-| expressions.swift:7:21:7:21 | DotSyntaxCallExpr |
-| expressions.swift:7:21:7:21 | InOutExpr |
-| expressions.swift:7:21:7:21 | StringLiteralExpr |
-| expressions.swift:8:15:8:15 | NilLiteralExpr |
-| expressions.swift:15:9:15:9 | DeclRefExpr |
-| expressions.swift:15:9:15:14 | BinaryExpr |
-| expressions.swift:15:11:15:11 | DeclRefExpr |
-| expressions.swift:15:11:15:11 | DotSyntaxCallExpr |
-| expressions.swift:15:11:15:11 | TypeExpr |
-| expressions.swift:15:14:15:14 | IntegerLiteralExpr |
-| expressions.swift:16:11:16:11 | TypeExpr |
-| expressions.swift:16:11:16:19 | DotSyntaxCallExpr |
-| expressions.swift:16:11:16:19 | ErasureExpr |
-| expressions.swift:16:19:16:19 | DeclRefExpr |
-| expressions.swift:20:1:20:16 | ForceTryExpr |
-| expressions.swift:20:6:20:6 | DeclRefExpr |
-| expressions.swift:20:6:20:16 | CallExpr |
-| expressions.swift:20:14:20:14 | IntegerLiteralExpr |
-| expressions.swift:21:1:21:16 | OptionalTryExpr |
-| expressions.swift:21:6:21:6 | DeclRefExpr |
-| expressions.swift:21:6:21:16 | CallExpr |
-| expressions.swift:21:6:21:16 | InjectIntoOptionalExpr |
-| expressions.swift:21:14:21:14 | IntegerLiteralExpr |
-| expressions.swift:27:13:27:13 | ConstructorRefCallExpr |
-| expressions.swift:27:13:27:13 | DeclRefExpr |
-| expressions.swift:27:13:27:13 | TypeExpr |
-| expressions.swift:27:13:27:19 | CallExpr |
-| expressions.swift:29:9:29:19 | DictionaryExpr |
-| expressions.swift:29:10:29:10 | StringLiteralExpr |
-| expressions.swift:29:10:29:16 | TupleExpr |
-| expressions.swift:29:16:29:16 | StringLiteralExpr |
-| expressions.swift:30:1:30:1 | DiscardAssignmentExpr |
-| expressions.swift:30:1:30:5 | AssignExpr |
-| expressions.swift:30:5:30:5 | IntegerLiteralExpr |
-| expressions.swift:31:1:31:1 | DiscardAssignmentExpr |
-| expressions.swift:31:1:31:11 | AssignExpr |
-| expressions.swift:31:5:31:5 | IntegerLiteralExpr |
-| expressions.swift:31:5:31:11 | IsExpr |
-| expressions.swift:32:1:32:1 | DiscardAssignmentExpr |
-| expressions.swift:32:1:32:11 | AssignExpr |
-| expressions.swift:32:5:32:5 | IntegerLiteralExpr |
-| expressions.swift:32:5:32:11 | CoerceExpr |
-| expressions.swift:33:1:33:1 | DiscardAssignmentExpr |
-| expressions.swift:33:1:33:12 | AssignExpr |
-| expressions.swift:33:5:33:5 | IntegerLiteralExpr |
-| expressions.swift:33:5:33:12 | ConditionalCheckedCastExpr |
-| expressions.swift:34:1:34:1 | DiscardAssignmentExpr |
-| expressions.swift:34:1:34:12 | AssignExpr |
-| expressions.swift:34:5:34:5 | IntegerLiteralExpr |
-| expressions.swift:34:5:34:12 | ForcedCheckedCastExpr |
-| expressions.swift:35:1:35:1 | DeclRefExpr |
-| expressions.swift:35:1:35:13 | CallExpr |
-| expressions.swift:35:6:35:6 | DefaultArgumentExpr |
-| expressions.swift:35:6:35:6 | DefaultArgumentExpr |
-| expressions.swift:35:7:35:7 | DeclRefExpr |
-| expressions.swift:35:7:35:12 | ArrayExpr |
-| expressions.swift:35:7:35:12 | ErasureExpr |
-| expressions.swift:35:7:35:12 | SubscriptExpr |
-| expressions.swift:35:7:35:12 | VarargExpansionExpr |
-| expressions.swift:35:9:35:9 | StringLiteralExpr |
-| expressions.swift:38:3:38:3 | DeclRefExpr |
-| expressions.swift:38:3:38:15 | CallExpr |
-| expressions.swift:38:11:38:11 | IntegerLiteralExpr |
-| expressions.swift:38:14:38:14 | IntegerLiteralExpr |
-| expressions.swift:41:1:41:1 | DeclRefExpr |
-| expressions.swift:41:1:43:1 | CallExpr |
-| expressions.swift:41:10:43:1 | ClosureExpr |
-| expressions.swift:42:12:42:12 | DeclRefExpr |
-| expressions.swift:42:12:42:16 | BinaryExpr |
-| expressions.swift:42:14:42:14 | DeclRefExpr |
-| expressions.swift:42:14:42:14 | DotSyntaxCallExpr |
-| expressions.swift:42:14:42:14 | TypeExpr |
-| expressions.swift:42:16:42:16 | DeclRefExpr |
-| expressions.swift:44:1:44:1 | DeclRefExpr |
-| expressions.swift:44:1:46:1 | CallExpr |
-| expressions.swift:44:10:46:1 | ClosureExpr |
-| expressions.swift:45:12:45:12 | DeclRefExpr |
-| expressions.swift:45:12:45:16 | BinaryExpr |
-| expressions.swift:45:14:45:14 | DeclRefExpr |
-| expressions.swift:45:14:45:14 | DotSyntaxCallExpr |
-| expressions.swift:45:14:45:14 | TypeExpr |
-| expressions.swift:45:16:45:16 | DeclRefExpr |
-| expressions.swift:47:1:47:1 | DeclRefExpr |
-| expressions.swift:47:1:47:27 | CallExpr |
-| expressions.swift:47:10:47:27 | ClosureExpr |
-| expressions.swift:47:19:47:19 | DeclRefExpr |
-| expressions.swift:47:19:47:24 | BinaryExpr |
-| expressions.swift:47:22:47:22 | DeclRefExpr |
-| expressions.swift:47:22:47:22 | DotSyntaxCallExpr |
-| expressions.swift:47:22:47:22 | TypeExpr |
-| expressions.swift:47:24:47:24 | DeclRefExpr |
-| expressions.swift:48:1:48:1 | DeclRefExpr |
-| expressions.swift:48:1:48:20 | CallExpr |
-| expressions.swift:48:10:48:20 | ClosureExpr |
-| expressions.swift:48:12:48:12 | DeclRefExpr |
-| expressions.swift:48:12:48:17 | BinaryExpr |
-| expressions.swift:48:15:48:15 | DeclRefExpr |
-| expressions.swift:48:15:48:15 | DotSyntaxCallExpr |
-| expressions.swift:48:15:48:15 | TypeExpr |
-| expressions.swift:48:17:48:17 | DeclRefExpr |
-| expressions.swift:54:1:54:1 | DiscardAssignmentExpr |
-| expressions.swift:54:1:54:8 | AssignExpr |
-| expressions.swift:54:5:54:8 | KeyPathExpr |
-| expressions.swift:58:16:58:16 | IntegerLiteralExpr |
-| expressions.swift:59:1:59:1 | DeclRefExpr |
-| expressions.swift:59:1:59:34 | CallExpr |
-| expressions.swift:59:25:59:26 | InOutExpr |
-| expressions.swift:59:25:59:26 | InOutToPointerExpr |
-| expressions.swift:59:26:59:26 | DeclRefExpr |
-| expressions.swift:60:1:60:1 | DeclRefExpr |
-| expressions.swift:60:1:60:63 | CallExpr |
-| expressions.swift:60:23:60:23 | DeclRefExpr |
-| expressions.swift:60:23:60:23 | LoadExpr |
-| expressions.swift:60:33:60:63 | ClosureExpr |
-| expressions.swift:60:33:60:63 | FunctionConversionExpr |
-| expressions.swift:60:35:60:35 | DeclRefExpr |
-| expressions.swift:60:35:60:61 | CallExpr |
-| expressions.swift:60:59:60:59 | DeclRefExpr |
-| expressions.swift:64:8:64:8 | DeclRefExpr |
-| expressions.swift:64:8:64:12 | BinaryExpr |
-| expressions.swift:64:10:64:10 | DeclRefExpr |
-| expressions.swift:64:10:64:10 | DotSyntaxCallExpr |
-| expressions.swift:64:10:64:10 | TypeExpr |
-| expressions.swift:64:12:64:12 | IntegerLiteralExpr |
-| expressions.swift:73:5:73:5 | DeclRefExpr |
-| expressions.swift:73:5:73:5 | MemberRefExpr |
-| expressions.swift:73:5:73:10 | AssignExpr |
-| expressions.swift:73:10:73:10 | DeclRefExpr |
-| expressions.swift:77:7:77:7 | CallExpr |
-| expressions.swift:77:7:77:7 | DeclRefExpr |
-| expressions.swift:77:7:77:7 | MagicIdentifierLiteralExpr |
-| expressions.swift:77:7:77:7 | MagicIdentifierLiteralExpr |
-| expressions.swift:77:7:77:7 | MagicIdentifierLiteralExpr |
-| expressions.swift:77:7:77:7 | MagicIdentifierLiteralExpr |
-| expressions.swift:77:7:77:7 | StringLiteralExpr |
-| expressions.swift:79:5:79:5 | SuperRefExpr |
-| expressions.swift:79:5:79:11 | DotSyntaxCallExpr |
-| expressions.swift:79:5:79:21 | CallExpr |
-| expressions.swift:79:5:79:21 | RebindSelfInConstructorExpr |
+| expressions.swift:7:10:7:10 | hello |
+| expressions.swift:7:11:7:10 | call to ... |
+| expressions.swift:7:11:7:11 | $interpolation |
+| expressions.swift:7:11:7:11 | &... |
+| expressions.swift:7:11:7:11 | call to appendLiteral |
+| expressions.swift:7:18:7:18 | $interpolation |
+| expressions.swift:7:18:7:18 | &... |
+| expressions.swift:7:18:7:18 | appendInterpolation |
+| expressions.swift:7:18:7:18 | call to appendInterpolation |
+| expressions.swift:7:18:7:20 | call to ... |
+| expressions.swift:7:19:7:19 | a |
+| expressions.swift:7:21:7:21 | |
+| expressions.swift:7:21:7:21 | $interpolation |
+| expressions.swift:7:21:7:21 | &... |
+| expressions.swift:7:21:7:21 | call to ... |
+| expressions.swift:7:21:7:21 | call to appendLiteral |
+| expressions.swift:8:15:8:15 | nil |
+| expressions.swift:15:9:15:9 | x |
+| expressions.swift:15:9:15:14 | ... call to != ... |
+| expressions.swift:15:11:15:11 | != |
+| expressions.swift:15:11:15:11 | Int.Type |
+| expressions.swift:15:11:15:11 | call to != |
+| expressions.swift:15:14:15:14 | 0 |
+| expressions.swift:16:11:16:11 | AnError.Type |
+| expressions.swift:16:11:16:19 | (Error) ... |
+| expressions.swift:16:11:16:19 | (TBD (ExistentialType)) ... |
+| expressions.swift:16:11:16:19 | call to ... |
+| expressions.swift:16:19:16:19 | failed |
+| expressions.swift:20:1:20:16 | try! ... |
+| expressions.swift:20:6:20:6 | failure |
+| expressions.swift:20:6:20:16 | call to failure |
+| expressions.swift:20:14:20:14 | 11 |
+| expressions.swift:21:1:21:16 | try? ... |
+| expressions.swift:21:6:21:6 | failure |
+| expressions.swift:21:6:21:16 | (()?) ... |
+| expressions.swift:21:6:21:16 | call to failure |
+| expressions.swift:21:14:21:14 | 11 |
+| expressions.swift:27:13:27:13 | Klass.Type |
+| expressions.swift:27:13:27:13 | call to ... |
+| expressions.swift:27:13:27:13 | deinit |
+| expressions.swift:27:13:27:19 | call to ... |
+| expressions.swift:29:9:29:19 | [...] |
+| expressions.swift:29:10:29:10 | 1 |
+| expressions.swift:29:10:29:16 | (...) |
+| expressions.swift:29:16:29:16 | 2 |
+| expressions.swift:30:1:30:1 | _ |
+| expressions.swift:30:1:30:5 | ... = ... |
+| expressions.swift:30:5:30:5 | 15 |
+| expressions.swift:31:1:31:1 | _ |
+| expressions.swift:31:1:31:11 | ... = ... |
+| expressions.swift:31:5:31:5 | 15 |
+| expressions.swift:31:5:31:11 | ... is ... |
+| expressions.swift:32:1:32:1 | _ |
+| expressions.swift:32:1:32:11 | ... = ... |
+| expressions.swift:32:5:32:5 | 15 |
+| expressions.swift:32:5:32:11 | (Double) ... |
+| expressions.swift:33:1:33:1 | _ |
+| expressions.swift:33:1:33:12 | ... = ... |
+| expressions.swift:33:5:33:5 | 15 |
+| expressions.swift:33:5:33:12 | (Double?) ... |
+| expressions.swift:34:1:34:1 | _ |
+| expressions.swift:34:1:34:12 | ... = ... |
+| expressions.swift:34:5:34:5 | 15 |
+| expressions.swift:34:5:34:12 | (Double) ... |
+| expressions.swift:35:1:35:1 | print |
+| expressions.swift:35:1:35:13 | call to print |
+| expressions.swift:35:6:35:6 | default separator |
+| expressions.swift:35:6:35:6 | default terminator |
+| expressions.swift:35:7:35:7 | d |
+| expressions.swift:35:7:35:12 | (Any) ... |
+| expressions.swift:35:7:35:12 | (TBD (ProtocolCompositionType)) ... |
+| expressions.swift:35:7:35:12 | ...[...] |
+| expressions.swift:35:7:35:12 | [...] |
+| expressions.swift:35:7:35:12 | [...] |
+| expressions.swift:35:9:35:9 | 1 |
+| expressions.swift:38:3:38:3 | closure |
+| expressions.swift:38:3:38:15 | call to ... |
+| expressions.swift:38:11:38:11 | 5 |
+| expressions.swift:38:14:38:14 | 7 |
+| expressions.swift:41:1:41:1 | closured |
+| expressions.swift:41:1:43:1 | call to closured |
+| expressions.swift:41:10:43:1 | { ... } |
+| expressions.swift:42:12:42:12 | x |
+| expressions.swift:42:12:42:16 | ... call to + ... |
+| expressions.swift:42:14:42:14 | + |
+| expressions.swift:42:14:42:14 | Int.Type |
+| expressions.swift:42:14:42:14 | call to + |
+| expressions.swift:42:16:42:16 | y |
+| expressions.swift:44:1:44:1 | closured |
+| expressions.swift:44:1:46:1 | call to closured |
+| expressions.swift:44:10:46:1 | { ... } |
+| expressions.swift:45:12:45:12 | x |
+| expressions.swift:45:12:45:16 | ... call to + ... |
+| expressions.swift:45:14:45:14 | + |
+| expressions.swift:45:14:45:14 | Int.Type |
+| expressions.swift:45:14:45:14 | call to + |
+| expressions.swift:45:16:45:16 | y |
+| expressions.swift:47:1:47:1 | closured |
+| expressions.swift:47:1:47:27 | call to closured |
+| expressions.swift:47:10:47:27 | { ... } |
+| expressions.swift:47:19:47:19 | $0 |
+| expressions.swift:47:19:47:24 | ... call to + ... |
+| expressions.swift:47:22:47:22 | + |
+| expressions.swift:47:22:47:22 | Int.Type |
+| expressions.swift:47:22:47:22 | call to + |
+| expressions.swift:47:24:47:24 | $1 |
+| expressions.swift:48:1:48:1 | closured |
+| expressions.swift:48:1:48:20 | call to closured |
+| expressions.swift:48:10:48:20 | { ... } |
+| expressions.swift:48:12:48:12 | $0 |
+| expressions.swift:48:12:48:17 | ... call to + ... |
+| expressions.swift:48:15:48:15 | + |
+| expressions.swift:48:15:48:15 | Int.Type |
+| expressions.swift:48:15:48:15 | call to + |
+| expressions.swift:48:17:48:17 | $1 |
+| expressions.swift:54:1:54:1 | _ |
+| expressions.swift:54:1:54:8 | ... = ... |
+| expressions.swift:54:5:54:8 | #keyPath(...) |
+| expressions.swift:58:16:58:16 | 1234 |
+| expressions.swift:59:1:59:1 | unsafeFunction |
+| expressions.swift:59:1:59:34 | call to unsafeFunction |
+| expressions.swift:59:25:59:26 | &... |
+| expressions.swift:59:25:59:26 | (UnsafePointer) ... |
+| expressions.swift:59:26:59:26 | myNumber |
+| expressions.swift:60:1:60:1 | withUnsafePointer |
+| expressions.swift:60:1:60:63 | call to withUnsafePointer |
+| expressions.swift:60:23:60:23 | (Int) ... |
+| expressions.swift:60:23:60:23 | myNumber |
+| expressions.swift:60:33:60:63 | ((UnsafePointer) throws -> ()) ... |
+| expressions.swift:60:33:60:63 | { ... } |
+| expressions.swift:60:35:60:35 | unsafeFunction |
+| expressions.swift:60:35:60:61 | call to unsafeFunction |
+| expressions.swift:60:59:60:59 | $0 |
+| expressions.swift:64:8:64:8 | x |
+| expressions.swift:64:8:64:12 | ... call to < ... |
+| expressions.swift:64:10:64:10 | < |
+| expressions.swift:64:10:64:10 | Int.Type |
+| expressions.swift:64:10:64:10 | call to < |
+| expressions.swift:64:12:64:12 | 0 |
+| expressions.swift:73:5:73:5 | .xx |
+| expressions.swift:73:5:73:5 | self |
+| expressions.swift:73:5:73:10 | ... = ... |
+| expressions.swift:73:10:73:10 | x |
+| expressions.swift:77:7:77:7 | #... |
+| expressions.swift:77:7:77:7 | #... |
+| expressions.swift:77:7:77:7 | #... |
+| expressions.swift:77:7:77:7 | #... |
+| expressions.swift:77:7:77:7 | _unimplementedInitializer |
+| expressions.swift:77:7:77:7 | call to _unimplementedInitializer |
+| expressions.swift:77:7:77:7 | expressions.Derived |
+| expressions.swift:79:5:79:5 | super |
+| expressions.swift:79:5:79:11 | call to ... |
+| expressions.swift:79:5:79:21 | call to ... |
+| expressions.swift:79:5:79:21 | self = ... |
| expressions.swift:79:11:79:11 | TBD (OtherConstructorDeclRefExpr) |
-| expressions.swift:79:19:79:19 | IntegerLiteralExpr |
-| expressions.swift:83:15:83:15 | ConstructorRefCallExpr |
-| expressions.swift:83:15:83:15 | DeclRefExpr |
-| expressions.swift:83:15:83:15 | TypeExpr |
-| expressions.swift:83:15:83:23 | CallExpr |
-| expressions.swift:84:1:84:1 | DiscardAssignmentExpr |
-| expressions.swift:84:1:84:13 | AssignExpr |
-| expressions.swift:84:5:84:5 | DeclRefExpr |
-| expressions.swift:84:5:84:5 | DerivedToBaseExpr |
-| expressions.swift:84:5:84:13 | MemberRefExpr |
-| expressions.swift:87:1:87:1 | DeclRefExpr |
-| expressions.swift:87:1:87:4 | ForceValueExpr |
-| expressions.swift:88:1:88:1 | DeclRefExpr |
-| expressions.swift:88:1:88:6 | SubscriptExpr |
-| expressions.swift:88:1:88:7 | ForceValueExpr |
-| expressions.swift:88:3:88:3 | StringLiteralExpr |
-| expressions.swift:92:14:92:14 | TypeExpr |
-| expressions.swift:92:14:92:24 | DotSyntaxCallExpr |
-| expressions.swift:92:14:92:44 | CallExpr |
-| expressions.swift:92:14:92:46 | DotSyntaxCallExpr |
-| expressions.swift:92:14:92:55 | CallExpr |
-| expressions.swift:92:24:92:24 | DeclRefExpr |
-| expressions.swift:92:37:92:37 | ConstructorRefCallExpr |
-| expressions.swift:92:37:92:37 | DeclRefExpr |
-| expressions.swift:92:37:92:37 | TypeExpr |
-| expressions.swift:92:37:92:43 | CallExpr |
-| expressions.swift:92:46:92:46 | DeclRefExpr |
-| expressions.swift:93:1:93:16 | TypeExpr |
-| expressions.swift:93:1:93:18 | DotSyntaxCallExpr |
-| expressions.swift:93:1:93:35 | CallExpr |
-| expressions.swift:93:18:93:18 | DeclRefExpr |
-| expressions.swift:93:29:93:29 | DeclRefExpr |
-| expressions.swift:93:29:93:29 | PointerToPointerExpr |
-| expressions.swift:99:14:99:14 | IntegerLiteralExpr |
-| expressions.swift:106:12:106:12 | IntegerLiteralExpr |
-| expressions.swift:112:14:112:14 | IntegerLiteralExpr |
-| expressions.swift:120:14:120:14 | IntegerLiteralExpr |
-| expressions.swift:126:12:126:12 | IntegerLiteralExpr |
-| expressions.swift:131:3:131:3 | DeclRefExpr |
-| expressions.swift:131:3:131:6 | MemberRefExpr |
-| expressions.swift:131:3:131:22 | AssignExpr |
-| expressions.swift:131:22:131:22 | IntegerLiteralExpr |
-| expressions.swift:132:11:132:11 | DeclRefExpr |
-| expressions.swift:132:11:132:14 | LoadExpr |
-| expressions.swift:132:11:132:14 | MemberRefExpr |
-| expressions.swift:133:11:133:11 | DeclRefExpr |
-| expressions.swift:133:11:133:11 | LoadExpr |
-| expressions.swift:133:11:133:14 | MemberRefExpr |
-| expressions.swift:134:11:134:11 | DeclRefExpr |
-| expressions.swift:134:11:134:11 | LoadExpr |
-| expressions.swift:134:11:134:14 | MemberRefExpr |
-| expressions.swift:135:3:135:3 | DeclRefExpr |
-| expressions.swift:135:3:135:6 | MemberRefExpr |
-| expressions.swift:135:3:135:20 | AssignExpr |
-| expressions.swift:135:20:135:20 | IntegerLiteralExpr |
-| expressions.swift:136:11:136:11 | DeclRefExpr |
-| expressions.swift:136:11:136:14 | LoadExpr |
-| expressions.swift:136:11:136:14 | MemberRefExpr |
-| expressions.swift:137:3:137:3 | DeclRefExpr |
-| expressions.swift:137:3:137:3 | InOutExpr |
-| expressions.swift:137:3:137:7 | SubscriptExpr |
-| expressions.swift:137:3:137:11 | AssignExpr |
-| expressions.swift:137:6:137:6 | IntegerLiteralExpr |
-| expressions.swift:137:11:137:11 | IntegerLiteralExpr |
-| expressions.swift:138:10:138:10 | DeclRefExpr |
-| expressions.swift:138:10:138:10 | LoadExpr |
-| expressions.swift:138:10:138:17 | SubscriptExpr |
-| expressions.swift:138:13:138:13 | IntegerLiteralExpr |
-| expressions.swift:138:16:138:16 | IntegerLiteralExpr |
+| expressions.swift:79:11:79:11 | call to ... |
+| expressions.swift:79:19:79:19 | 22 |
+| expressions.swift:83:15:83:15 | Derived.Type |
+| expressions.swift:83:15:83:15 | call to ... |
+| expressions.swift:83:15:83:15 | deinit |
+| expressions.swift:83:15:83:23 | call to ... |
+| expressions.swift:84:1:84:1 | _ |
+| expressions.swift:84:1:84:13 | ... = ... |
+| expressions.swift:84:5:84:5 | (Base) ... |
+| expressions.swift:84:5:84:5 | derived |
+| expressions.swift:84:5:84:13 | .xx |
+| expressions.swift:87:1:87:1 | opt |
+| expressions.swift:87:1:87:4 | ...! |
+| expressions.swift:88:1:88:1 | d |
+| expressions.swift:88:1:88:6 | ...[...] |
+| expressions.swift:88:1:88:7 | ...! |
+| expressions.swift:88:3:88:3 | a |
+| expressions.swift:92:14:92:14 | Unmanaged.Type |
+| expressions.swift:92:14:92:24 | call to passRetained |
+| expressions.swift:92:14:92:44 | call to ... |
+| expressions.swift:92:14:92:46 | call to toOpaque |
+| expressions.swift:92:14:92:55 | call to ... |
+| expressions.swift:92:24:92:24 | passRetained |
+| expressions.swift:92:37:92:37 | ToPtr.Type |
+| expressions.swift:92:37:92:37 | call to ... |
+| expressions.swift:92:37:92:37 | deinit |
+| expressions.swift:92:37:92:43 | call to ... |
+| expressions.swift:92:46:92:46 | toOpaque |
+| expressions.swift:93:1:93:16 | Unmanaged.Type |
+| expressions.swift:93:1:93:18 | call to fromOpaque |
+| expressions.swift:93:1:93:35 | call to ... |
+| expressions.swift:93:18:93:18 | fromOpaque |
+| expressions.swift:93:29:93:29 | (UnsafeRawPointer) ... |
+| expressions.swift:93:29:93:29 | opaque |
+| expressions.swift:99:14:99:14 | 0 |
+| expressions.swift:106:12:106:12 | 0 |
+| expressions.swift:112:14:112:14 | 0 |
+| expressions.swift:120:14:120:14 | 0 |
+| expressions.swift:126:12:126:12 | 0 |
+| expressions.swift:131:3:131:3 | hp |
+| expressions.swift:131:3:131:6 | .settableField |
+| expressions.swift:131:3:131:22 | ... = ... |
+| expressions.swift:131:22:131:22 | 42 |
+| expressions.swift:132:11:132:11 | hp |
+| expressions.swift:132:11:132:14 | (Int) ... |
+| expressions.swift:132:11:132:14 | .settableField |
+| expressions.swift:133:11:133:11 | (HasProperty) ... |
+| expressions.swift:133:11:133:11 | hp |
+| expressions.swift:133:11:133:14 | .readOnlyField1 |
+| expressions.swift:134:11:134:11 | (HasProperty) ... |
+| expressions.swift:134:11:134:11 | hp |
+| expressions.swift:134:11:134:14 | .readOnlyField2 |
+| expressions.swift:135:3:135:3 | hp |
+| expressions.swift:135:3:135:6 | .normalField |
+| expressions.swift:135:3:135:20 | ... = ... |
+| expressions.swift:135:20:135:20 | 99 |
+| expressions.swift:136:11:136:11 | hp |
+| expressions.swift:136:11:136:14 | (Int) ... |
+| expressions.swift:136:11:136:14 | .normalField |
+| expressions.swift:137:3:137:3 | &... |
+| expressions.swift:137:3:137:3 | hp |
+| expressions.swift:137:3:137:7 | ...[...] |
+| expressions.swift:137:3:137:11 | ... = ... |
+| expressions.swift:137:6:137:6 | 1 |
+| expressions.swift:137:11:137:11 | 2 |
+| expressions.swift:138:10:138:10 | (HasProperty) ... |
+| expressions.swift:138:10:138:10 | hp |
+| expressions.swift:138:10:138:17 | ...[...] |
+| expressions.swift:138:13:138:13 | 3 |
+| expressions.swift:138:16:138:16 | 4 |
diff --git a/swift/ql/test/extractor-tests/expressions/semantics.expected b/swift/ql/test/extractor-tests/expressions/semantics.expected
index c20d4a29b93..5f07b18715f 100644
--- a/swift/ql/test/extractor-tests/expressions/semantics.expected
+++ b/swift/ql/test/extractor-tests/expressions/semantics.expected
@@ -1,70 +1,70 @@
-| expressions.swift:7:11:7:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:7:18:7:18 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:7:18:7:18 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:7:19:7:19 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:7:21:7:21 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:15:9:15:9 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:15:11:15:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:16:19:16:19 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:20:6:20:6 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:21:6:21:6 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:27:13:27:13 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:35:1:35:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:35:7:35:7 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:35:7:35:12 | SubscriptExpr | OrdinarySemantics |
-| expressions.swift:38:3:38:3 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:41:1:41:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:42:12:42:12 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:42:14:42:14 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:42:16:42:16 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:44:1:44:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:45:12:45:12 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:45:14:45:14 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:45:16:45:16 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:47:1:47:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:47:19:47:19 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:47:22:47:22 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:47:24:47:24 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:48:1:48:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:48:12:48:12 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:48:15:48:15 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:48:17:48:17 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:59:1:59:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:59:26:59:26 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:60:1:60:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:60:23:60:23 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:60:35:60:35 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:60:59:60:59 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:64:8:64:8 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:64:10:64:10 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:73:5:73:5 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:73:5:73:5 | MemberRefExpr | DirectToStorage |
-| expressions.swift:73:10:73:10 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:77:7:77:7 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:83:15:83:15 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:84:5:84:5 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:84:5:84:13 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:87:1:87:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:88:1:88:1 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:88:1:88:6 | SubscriptExpr | OrdinarySemantics |
-| expressions.swift:92:24:92:24 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:92:37:92:37 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:92:46:92:46 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:93:18:93:18 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:93:29:93:29 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:131:3:131:3 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:131:3:131:6 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:132:11:132:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:132:11:132:14 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:133:11:133:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:133:11:133:14 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:134:11:134:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:134:11:134:14 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:135:3:135:3 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:135:3:135:6 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:136:11:136:11 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:136:11:136:14 | MemberRefExpr | OrdinarySemantics |
-| expressions.swift:137:3:137:3 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:137:3:137:7 | SubscriptExpr | OrdinarySemantics |
-| expressions.swift:138:10:138:10 | DeclRefExpr | OrdinarySemantics |
-| expressions.swift:138:10:138:17 | SubscriptExpr | OrdinarySemantics |
+| expressions.swift:7:11:7:11 | $interpolation | OrdinarySemantics |
+| expressions.swift:7:18:7:18 | $interpolation | OrdinarySemantics |
+| expressions.swift:7:18:7:18 | appendInterpolation | OrdinarySemantics |
+| expressions.swift:7:19:7:19 | a | OrdinarySemantics |
+| expressions.swift:7:21:7:21 | $interpolation | OrdinarySemantics |
+| expressions.swift:15:9:15:9 | x | OrdinarySemantics |
+| expressions.swift:15:11:15:11 | != | OrdinarySemantics |
+| expressions.swift:16:19:16:19 | failed | OrdinarySemantics |
+| expressions.swift:20:6:20:6 | failure | OrdinarySemantics |
+| expressions.swift:21:6:21:6 | failure | OrdinarySemantics |
+| expressions.swift:27:13:27:13 | deinit | OrdinarySemantics |
+| expressions.swift:35:1:35:1 | print | OrdinarySemantics |
+| expressions.swift:35:7:35:7 | d | OrdinarySemantics |
+| expressions.swift:35:7:35:12 | ...[...] | OrdinarySemantics |
+| expressions.swift:38:3:38:3 | closure | OrdinarySemantics |
+| expressions.swift:41:1:41:1 | closured | OrdinarySemantics |
+| expressions.swift:42:12:42:12 | x | OrdinarySemantics |
+| expressions.swift:42:14:42:14 | + | OrdinarySemantics |
+| expressions.swift:42:16:42:16 | y | OrdinarySemantics |
+| expressions.swift:44:1:44:1 | closured | OrdinarySemantics |
+| expressions.swift:45:12:45:12 | x | OrdinarySemantics |
+| expressions.swift:45:14:45:14 | + | OrdinarySemantics |
+| expressions.swift:45:16:45:16 | y | OrdinarySemantics |
+| expressions.swift:47:1:47:1 | closured | OrdinarySemantics |
+| expressions.swift:47:19:47:19 | $0 | OrdinarySemantics |
+| expressions.swift:47:22:47:22 | + | OrdinarySemantics |
+| expressions.swift:47:24:47:24 | $1 | OrdinarySemantics |
+| expressions.swift:48:1:48:1 | closured | OrdinarySemantics |
+| expressions.swift:48:12:48:12 | $0 | OrdinarySemantics |
+| expressions.swift:48:15:48:15 | + | OrdinarySemantics |
+| expressions.swift:48:17:48:17 | $1 | OrdinarySemantics |
+| expressions.swift:59:1:59:1 | unsafeFunction | OrdinarySemantics |
+| expressions.swift:59:26:59:26 | myNumber | OrdinarySemantics |
+| expressions.swift:60:1:60:1 | withUnsafePointer | OrdinarySemantics |
+| expressions.swift:60:23:60:23 | myNumber | OrdinarySemantics |
+| expressions.swift:60:35:60:35 | unsafeFunction | OrdinarySemantics |
+| expressions.swift:60:59:60:59 | $0 | OrdinarySemantics |
+| expressions.swift:64:8:64:8 | x | OrdinarySemantics |
+| expressions.swift:64:10:64:10 | < | OrdinarySemantics |
+| expressions.swift:73:5:73:5 | .xx | DirectToStorage |
+| expressions.swift:73:5:73:5 | self | OrdinarySemantics |
+| expressions.swift:73:10:73:10 | x | OrdinarySemantics |
+| expressions.swift:77:7:77:7 | _unimplementedInitializer | OrdinarySemantics |
+| expressions.swift:83:15:83:15 | deinit | OrdinarySemantics |
+| expressions.swift:84:5:84:5 | derived | OrdinarySemantics |
+| expressions.swift:84:5:84:13 | .xx | OrdinarySemantics |
+| expressions.swift:87:1:87:1 | opt | OrdinarySemantics |
+| expressions.swift:88:1:88:1 | d | OrdinarySemantics |
+| expressions.swift:88:1:88:6 | ...[...] | OrdinarySemantics |
+| expressions.swift:92:24:92:24 | passRetained | OrdinarySemantics |
+| expressions.swift:92:37:92:37 | deinit | OrdinarySemantics |
+| expressions.swift:92:46:92:46 | toOpaque | OrdinarySemantics |
+| expressions.swift:93:18:93:18 | fromOpaque | OrdinarySemantics |
+| expressions.swift:93:29:93:29 | opaque | OrdinarySemantics |
+| expressions.swift:131:3:131:3 | hp | OrdinarySemantics |
+| expressions.swift:131:3:131:6 | .settableField | OrdinarySemantics |
+| expressions.swift:132:11:132:11 | hp | OrdinarySemantics |
+| expressions.swift:132:11:132:14 | .settableField | OrdinarySemantics |
+| expressions.swift:133:11:133:11 | hp | OrdinarySemantics |
+| expressions.swift:133:11:133:14 | .readOnlyField1 | OrdinarySemantics |
+| expressions.swift:134:11:134:11 | hp | OrdinarySemantics |
+| expressions.swift:134:11:134:14 | .readOnlyField2 | OrdinarySemantics |
+| expressions.swift:135:3:135:3 | hp | OrdinarySemantics |
+| expressions.swift:135:3:135:6 | .normalField | OrdinarySemantics |
+| expressions.swift:136:11:136:11 | hp | OrdinarySemantics |
+| expressions.swift:136:11:136:14 | .normalField | OrdinarySemantics |
+| expressions.swift:137:3:137:3 | hp | OrdinarySemantics |
+| expressions.swift:137:3:137:7 | ...[...] | OrdinarySemantics |
+| expressions.swift:138:10:138:10 | hp | OrdinarySemantics |
+| expressions.swift:138:10:138:17 | ...[...] | OrdinarySemantics |
diff --git a/swift/ql/test/extractor-tests/patterns/all.expected b/swift/ql/test/extractor-tests/patterns/all.expected
index af4caf5feff..5547d4efbd5 100644
--- a/swift/ql/test/extractor-tests/patterns/all.expected
+++ b/swift/ql/test/extractor-tests/patterns/all.expected
@@ -1,41 +1,41 @@
-| patterns.swift:2:9:2:9 | NamedPattern |
-| patterns.swift:3:9:3:9 | NamedPattern |
-| patterns.swift:3:9:3:19 | TypedPattern |
-| patterns.swift:4:9:4:17 | TuplePattern |
-| patterns.swift:4:10:4:10 | NamedPattern |
-| patterns.swift:4:13:4:13 | NamedPattern |
-| patterns.swift:4:16:4:16 | NamedPattern |
-| patterns.swift:5:9:5:9 | AnyPattern |
-| patterns.swift:6:9:6:11 | ParenPattern |
-| patterns.swift:6:10:6:10 | AnyPattern |
-| patterns.swift:10:9:10:9 | NamedPattern |
-| patterns.swift:12:10:12:21 | BindingPattern |
-| patterns.swift:12:14:12:21 | TuplePattern |
-| patterns.swift:12:15:12:15 | NamedPattern |
-| patterns.swift:12:19:12:19 | NamedPattern |
-| patterns.swift:16:10:16:14 | ExprPattern |
-| patterns.swift:17:10:17:10 | AnyPattern |
-| patterns.swift:24:9:24:9 | NamedPattern |
-| patterns.swift:24:9:24:12 | TypedPattern |
-| patterns.swift:27:10:27:11 | EnumElementPattern |
-| patterns.swift:28:10:28:23 | BindingPattern |
-| patterns.swift:28:14:28:23 | EnumElementPattern |
-| patterns.swift:28:18:28:23 | TuplePattern |
-| patterns.swift:28:19:28:19 | NamedPattern |
-| patterns.swift:28:22:28:22 | NamedPattern |
-| patterns.swift:31:9:31:9 | NamedPattern |
-| patterns.swift:31:9:31:15 | TypedPattern |
-| patterns.swift:34:10:34:15 | BindingPattern |
-| patterns.swift:34:14:34:14 | NamedPattern |
-| patterns.swift:34:14:34:15 | OptionalSomePattern |
-| patterns.swift:35:10:35:10 | AnyPattern |
-| patterns.swift:38:9:38:9 | NamedPattern |
-| patterns.swift:38:9:38:12 | TypedPattern |
-| patterns.swift:41:10:41:13 | IsPattern |
-| patterns.swift:42:10:42:19 | BindingPattern |
-| patterns.swift:42:14:42:14 | NamedPattern |
-| patterns.swift:42:14:42:19 | IsPattern |
-| patterns.swift:43:10:43:10 | AnyPattern |
-| patterns.swift:46:9:46:9 | NamedPattern |
-| patterns.swift:49:10:49:10 | BoolPattern |
-| patterns.swift:50:10:50:10 | BoolPattern |
+| patterns.swift:2:9:2:9 | an_int |
+| patterns.swift:3:9:3:9 | a_string |
+| patterns.swift:3:9:3:19 | ... as ... |
+| patterns.swift:4:9:4:17 | (...) |
+| patterns.swift:4:10:4:10 | x |
+| patterns.swift:4:13:4:13 | y |
+| patterns.swift:4:16:4:16 | z |
+| patterns.swift:5:9:5:9 | _ |
+| patterns.swift:6:9:6:11 | (...) |
+| patterns.swift:6:10:6:10 | _ |
+| patterns.swift:10:9:10:9 | point |
+| patterns.swift:12:10:12:21 | let ... |
+| patterns.swift:12:14:12:21 | (...) |
+| patterns.swift:12:15:12:15 | xx |
+| patterns.swift:12:19:12:19 | yy |
+| patterns.swift:16:10:16:14 | TBD (SequenceExpr) |
+| patterns.swift:17:10:17:10 | _ |
+| patterns.swift:24:9:24:9 | v |
+| patterns.swift:24:9:24:12 | ... as ... |
+| patterns.swift:27:10:27:11 | .bar |
+| patterns.swift:28:10:28:23 | let ... |
+| patterns.swift:28:14:28:23 | .baz(...) |
+| patterns.swift:28:18:28:23 | (...) |
+| patterns.swift:28:19:28:19 | i |
+| patterns.swift:28:22:28:22 | s |
+| patterns.swift:31:9:31:9 | w |
+| patterns.swift:31:9:31:15 | ... as ... |
+| patterns.swift:34:10:34:15 | let ... |
+| patterns.swift:34:14:34:14 | n |
+| patterns.swift:34:14:34:15 | let ...? |
+| patterns.swift:35:10:35:10 | _ |
+| patterns.swift:38:9:38:9 | a |
+| patterns.swift:38:9:38:12 | ... as ... |
+| patterns.swift:41:10:41:13 | ... is ... |
+| patterns.swift:42:10:42:19 | let ... |
+| patterns.swift:42:14:42:14 | x |
+| patterns.swift:42:14:42:19 | ... is ... |
+| patterns.swift:43:10:43:10 | _ |
+| patterns.swift:46:9:46:9 | b |
+| patterns.swift:49:10:49:10 | true |
+| patterns.swift:50:10:50:10 | false |
diff --git a/swift/ql/test/extractor-tests/statements/ConditionElements.expected b/swift/ql/test/extractor-tests/statements/ConditionElements.expected
index 7b7c3eb3de8..9800a5a6967 100644
--- a/swift/ql/test/extractor-tests/statements/ConditionElements.expected
+++ b/swift/ql/test/extractor-tests/statements/ConditionElements.expected
@@ -1,7 +1,11 @@
-| main.swift:3:8:3:13 | ConditionElement | main.swift:3:8:3:13 | BinaryExpr |
-| main.swift:10:17:10:24 | ConditionElement | main.swift:10:18:10:22 | BinaryExpr |
-| main.swift:39:9:39:14 | ConditionElement | main.swift:39:9:39:14 | BinaryExpr |
-| main.swift:65:4:65:19 | ConditionElement | main.swift:65:9:65:15 | BindingPattern |
-| main.swift:65:4:65:19 | ConditionElement | main.swift:65:19:65:19 | DeclRefExpr |
-| main.swift:67:4:67:20 | ConditionElement | main.swift:67:9:67:16 | EnumElementPattern |
-| main.swift:67:4:67:20 | ConditionElement | main.swift:67:20:67:20 | DeclRefExpr |
+| main.swift:3:8:3:13 | ... call to == ... | main.swift:3:8:3:13 | ... call to == ... |
+| main.swift:10:17:10:24 | ... call to < ... | main.swift:10:18:10:22 | ... call to < ... |
+| main.swift:39:9:39:14 | ... call to != ... | main.swift:39:9:39:14 | ... call to != ... |
+| main.swift:65:4:65:19 | let ... | main.swift:65:9:65:15 | let ... |
+| main.swift:65:4:65:19 | let ... | main.swift:65:19:65:19 | x |
+| main.swift:65:4:65:19 | x | main.swift:65:9:65:15 | let ... |
+| main.swift:65:4:65:19 | x | main.swift:65:19:65:19 | x |
+| main.swift:67:4:67:20 | .some(...) | main.swift:67:9:67:16 | .some(...) |
+| main.swift:67:4:67:20 | .some(...) | main.swift:67:20:67:20 | x |
+| main.swift:67:4:67:20 | x | main.swift:67:9:67:16 | .some(...) |
+| main.swift:67:4:67:20 | x | main.swift:67:20:67:20 | x |
diff --git a/swift/ql/test/extractor-tests/statements/LabeledStmts.expected b/swift/ql/test/extractor-tests/statements/LabeledStmts.expected
index 99a58ea9e82..8f7e9199113 100644
--- a/swift/ql/test/extractor-tests/statements/LabeledStmts.expected
+++ b/swift/ql/test/extractor-tests/statements/LabeledStmts.expected
@@ -1,12 +1,12 @@
-| main.swift:2:3:8:3 | ForEachStmt |
-| main.swift:3:5:7:5 | IfStmt |
-| main.swift:10:3:12:3 | WhileStmt |
-| main.swift:15:3:17:18 | RepeatWhileStmt |
-| main.swift:19:3:23:3 | DoCatchStmt |
-| main.swift:25:3:31:3 | DoCatchStmt |
-| main.swift:39:3:41:3 | GuardStmt |
-| main.swift:48:1:50:1 | DoStmt |
-| main.swift:53:1:62:1 | SwitchStmt |
-| main.swift:65:1:66:1 | IfStmt |
-| main.swift:67:1:68:1 | IfStmt |
-| main.swift:71:1:72:1 | ForEachStmt |
+| main.swift:2:3:8:3 | for ... in ... { ... } |
+| main.swift:3:5:7:5 | if ... then { ... } else { ... } |
+| main.swift:10:3:12:3 | while ... { ... } |
+| main.swift:15:3:17:18 | repeat { ... } while ... |
+| main.swift:19:3:23:3 | do { ... } catch { ... } |
+| main.swift:25:3:31:3 | do { ... } catch { ... } |
+| main.swift:39:3:41:3 | guard ... else { ... } |
+| main.swift:48:1:50:1 | do { ... } |
+| main.swift:53:1:62:1 | switch index { ... } |
+| main.swift:65:1:66:1 | if ... then { ... } |
+| main.swift:67:1:68:1 | if ... then { ... } |
+| main.swift:71:1:72:1 | for ... in ... where ... { ... } |
diff --git a/swift/ql/test/extractor-tests/statements/Labels.expected b/swift/ql/test/extractor-tests/statements/Labels.expected
index d00e90e0260..035b823b168 100644
--- a/swift/ql/test/extractor-tests/statements/Labels.expected
+++ b/swift/ql/test/extractor-tests/statements/Labels.expected
@@ -1,3 +1,3 @@
-| main.swift:2:3:8:3 | ForEachStmt | label1 |
-| main.swift:10:3:12:3 | WhileStmt | label2 |
-| main.swift:15:3:17:18 | RepeatWhileStmt | label3 |
+| main.swift:2:3:8:3 | for ... in ... { ... } | label1 |
+| main.swift:10:3:12:3 | while ... { ... } | label2 |
+| main.swift:15:3:17:18 | repeat { ... } while ... | label3 |
diff --git a/swift/ql/test/extractor-tests/types/ClassDecls.expected b/swift/ql/test/extractor-tests/types/ClassDecls.expected
index d70b5531583..28ca13f6199 100644
--- a/swift/ql/test/extractor-tests/types/ClassDecls.expected
+++ b/swift/ql/test/extractor-tests/types/ClassDecls.expected
@@ -1,2 +1,2 @@
-| types.swift:9:1:11:1 | ClassDecl | ClassType | |
-| types.swift:10:1:10:15 | ClassDecl | ClassType | ClassType |
+| types.swift:9:1:11:1 | C | C | |
+| types.swift:10:1:10:15 | Nested | C.Nested | C |
diff --git a/swift/ql/test/extractor-tests/types/StructDecls.expected b/swift/ql/test/extractor-tests/types/StructDecls.expected
index a080b049f0b..f25c1d052dc 100644
--- a/swift/ql/test/extractor-tests/types/StructDecls.expected
+++ b/swift/ql/test/extractor-tests/types/StructDecls.expected
@@ -1 +1 @@
-| types.swift:5:1:5:11 | StructDecl | StructType | |
+| types.swift:5:1:5:11 | X | X | |
diff --git a/swift/ql/test/extractor-tests/types/ThrowingAndAsync.expected b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.expected
new file mode 100644
index 00000000000..c9fe5db7b41
--- /dev/null
+++ b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.expected
@@ -0,0 +1,4 @@
+| types.swift:24:1:26:1 | throwingFunc | () throws -> Int | throws |
+| types.swift:28:1:28:36 | asyncFunction | (Int) async -> () | async |
+| types.swift:30:1:30:54 | throwingAndAsyncFunction | (Int) async throws -> () | async |
+| types.swift:30:1:30:54 | throwingAndAsyncFunction | (Int) async throws -> () | throws |
diff --git a/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql
new file mode 100644
index 00000000000..f0f6c90f879
--- /dev/null
+++ b/swift/ql/test/extractor-tests/types/ThrowingAndAsync.ql
@@ -0,0 +1,12 @@
+import codeql.swift.elements
+
+from FuncDecl f, AnyFunctionType t, string s
+where
+ f.getInterfaceType() = t and
+ f.getLocation().getFile().getName().matches("%swift/ql/test%") and
+ (
+ t.isAsync() and s = "async"
+ or
+ t.isThrowing() and s = "throws"
+ )
+select f, t, s
diff --git a/swift/ql/test/extractor-tests/types/Types.expected b/swift/ql/test/extractor-tests/types/Types.expected
index 052c66b8b74..3f08b50968c 100644
--- a/swift/ql/test/extractor-tests/types/Types.expected
+++ b/swift/ql/test/extractor-tests/types/Types.expected
@@ -1,35 +1,41 @@
-| types.swift:1:9:1:9 | IntegerLiteralExpr | StructType |
-| types.swift:3:1:3:1 | DeclRefExpr | FunctionType |
-| types.swift:3:1:3:13 | CallExpr | TupleType |
-| types.swift:3:6:3:6 | DefaultArgumentExpr | StructType |
-| types.swift:3:6:3:6 | DefaultArgumentExpr | StructType |
-| types.swift:3:7:3:7 | DeclRefExpr | StructType |
-| types.swift:3:7:3:11 | ArrayExpr | TBD (VariadicSequenceType) |
-| types.swift:3:7:3:11 | BinaryExpr | StructType |
-| types.swift:3:7:3:11 | ErasureExpr | TBD (ProtocolCompositionType) |
-| types.swift:3:7:3:11 | VarargExpansionExpr | TBD (VariadicSequenceType) |
-| types.swift:3:9:3:9 | DeclRefExpr | FunctionType |
-| types.swift:3:9:3:9 | DotSyntaxCallExpr | FunctionType |
-| types.swift:3:9:3:9 | TypeExpr | MetatypeType |
-| types.swift:3:11:3:11 | IntegerLiteralExpr | StructType |
-| types.swift:7:16:7:16 | ConstructorRefCallExpr | FunctionType |
-| types.swift:7:16:7:16 | DeclRefExpr | FunctionType |
-| types.swift:7:16:7:16 | TypeExpr | MetatypeType |
-| types.swift:7:16:7:18 | CallExpr | StructType |
-| types.swift:13:17:13:17 | ConstructorRefCallExpr | FunctionType |
-| types.swift:13:17:13:17 | DeclRefExpr | FunctionType |
-| types.swift:13:17:13:17 | TypeExpr | MetatypeType |
-| types.swift:13:17:13:19 | CallExpr | ClassType |
-| types.swift:14:22:14:24 | ConstructorRefCallExpr | FunctionType |
-| types.swift:14:22:14:24 | TypeExpr | MetatypeType |
-| types.swift:14:22:14:31 | CallExpr | ClassType |
-| types.swift:14:24:14:24 | DeclRefExpr | FunctionType |
-| types.swift:17:10:17:10 | DeclRefExpr | StructType |
-| types.swift:17:10:17:14 | BinaryExpr | StructType |
-| types.swift:17:12:17:12 | DeclRefExpr | FunctionType |
-| types.swift:17:12:17:12 | DotSyntaxCallExpr | FunctionType |
-| types.swift:17:12:17:12 | TypeExpr | MetatypeType |
-| types.swift:17:14:17:14 | DeclRefExpr | StructType |
-| types.swift:21:10:21:10 | DeclRefExpr | FunctionType |
-| types.swift:21:10:21:13 | CallExpr | StructType |
-| types.swift:21:12:21:12 | DeclRefExpr | StructType |
+| types.swift:1:9:1:9 | 42 | Int |
+| types.swift:3:1:3:1 | print | (Any..., String, String) -> () |
+| types.swift:3:1:3:13 | call to print | () |
+| types.swift:3:6:3:6 | default separator | String |
+| types.swift:3:6:3:6 | default terminator | String |
+| types.swift:3:7:3:7 | x | Int |
+| types.swift:3:7:3:11 | (Any) ... | Any |
+| types.swift:3:7:3:11 | (Any) ... | TBD (ProtocolCompositionType) |
+| types.swift:3:7:3:11 | (TBD (ProtocolCompositionType)) ... | Any |
+| types.swift:3:7:3:11 | (TBD (ProtocolCompositionType)) ... | TBD (ProtocolCompositionType) |
+| types.swift:3:7:3:11 | ... call to + ... | Int |
+| types.swift:3:7:3:11 | [...] | Any... |
+| types.swift:3:7:3:11 | [...] | Any... |
+| types.swift:3:7:3:11 | [...] | TBD (VariadicSequenceType) |
+| types.swift:3:7:3:11 | [...] | TBD (VariadicSequenceType) |
+| types.swift:3:9:3:9 | + | (Int.Type) -> (Int, Int) -> Int |
+| types.swift:3:9:3:9 | Int.Type | Int.Type |
+| types.swift:3:9:3:9 | call to + | (Int, Int) -> Int |
+| types.swift:3:11:3:11 | 10 | Int |
+| types.swift:7:16:7:16 | X.Type | X.Type |
+| types.swift:7:16:7:16 | call to ... | () -> X |
+| types.swift:7:16:7:16 | deinit | (X.Type) -> () -> X |
+| types.swift:7:16:7:18 | call to ... | X |
+| types.swift:13:17:13:17 | C.Type | C.Type |
+| types.swift:13:17:13:17 | call to ... | () -> C |
+| types.swift:13:17:13:17 | deinit | (C.Type) -> () -> C |
+| types.swift:13:17:13:19 | call to ... | C |
+| types.swift:14:22:14:24 | C.Nested.Type | C.Nested.Type |
+| types.swift:14:22:14:24 | call to ... | () -> C.Nested |
+| types.swift:14:22:14:31 | call to ... | C.Nested |
+| types.swift:14:24:14:24 | deinit | (C.Nested.Type) -> () -> C.Nested |
+| types.swift:17:10:17:10 | x | Int |
+| types.swift:17:10:17:14 | ... call to + ... | Int |
+| types.swift:17:12:17:12 | + | (Int.Type) -> (Int, Int) -> Int |
+| types.swift:17:12:17:12 | Int.Type | Int.Type |
+| types.swift:17:12:17:12 | call to + | (Int, Int) -> Int |
+| types.swift:17:14:17:14 | y | Int |
+| types.swift:21:10:21:10 | f | (Int) -> Int |
+| types.swift:21:10:21:13 | call to ... | Int |
+| types.swift:21:12:21:12 | x | Int |
+| types.swift:25:10:25:10 | 42 | Int |
diff --git a/swift/ql/test/extractor-tests/types/types.swift b/swift/ql/test/extractor-tests/types/types.swift
index 1eb8a56c452..b7b225d07db 100644
--- a/swift/ql/test/extractor-tests/types/types.swift
+++ b/swift/ql/test/extractor-tests/types/types.swift
@@ -20,3 +20,11 @@ func f(x: Int, y: Int) -> Int {
func g(_ f: (Int) -> Int, _ x: Int) -> Int {
return f(x)
}
+
+func throwingFunc() throws -> Int {
+ return 42
+}
+
+func asyncFunction(x: Int) async { }
+
+func throwingAndAsyncFunction(x: Int) async throws { }
\ No newline at end of file
diff --git a/swift/ql/test/library-tests/controlflow/graph/Cfg.expected b/swift/ql/test/library-tests/controlflow/graph/Cfg.expected
index 08ecb747577..1a6485f84f6 100644
--- a/swift/ql/test/library-tests/controlflow/graph/Cfg.expected
+++ b/swift/ql/test/library-tests/controlflow/graph/Cfg.expected
@@ -1,4790 +1,4935 @@
cfg.swift:
-# 5| enter ConcreteFuncDecl
-#-----| -> IntegerLiteralExpr
+# 5| enter returnZero
+#-----| -> 0
-# 5| exit ConcreteFuncDecl
+# 5| exit returnZero
-# 5| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 5| exit returnZero (normal)
+#-----| -> exit returnZero
-# 5| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 5| return ...
+#-----| return -> exit returnZero (normal)
-# 5| IntegerLiteralExpr
-#-----| -> ReturnStmt
+# 5| 0
+#-----| -> return ...
-# 15| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 15| enter isZero
+#-----| -> ==
-# 15| exit ConcreteFuncDecl
+# 15| exit isZero
-# 15| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 15| exit isZero (normal)
+#-----| -> exit isZero
-# 15| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 15| return ...
+#-----| return -> exit isZero (normal)
-# 15| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 15| x
+#-----| -> 0
-# 15| BinaryExpr
-#-----| -> ReturnStmt
+# 15| ... call to == ...
+#-----| -> return ...
-# 15| DeclRefExpr
-#-----| -> TypeExpr
+# 15| ==
+#-----| -> Int.Type
-# 15| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 15| Int.Type
+#-----| -> call to ==
-# 15| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 15| call to ==
+#-----| exception -> exit isZero (normal)
+#-----| -> x
-# 15| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 15| 0
+#-----| -> ... call to == ...
-# 17| enter ConcreteFuncDecl
-#-----| -> GuardStmt
+# 17| enter mightThrow
+#-----| -> guard ... else { ... }
-# 17| exit ConcreteFuncDecl
+# 17| exit mightThrow
-# 17| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 17| exit mightThrow (normal)
+#-----| -> exit mightThrow
-# 18| GuardStmt
-#-----| -> DeclRefExpr
+# 18| guard ... else { ... }
+#-----| -> >=
-# 18| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 18| x
+#-----| -> 0
-# 18| BinaryExpr
+# 18| ... call to >= ...
#-----| -> StmtCondition
# 18| StmtCondition
-#-----| false -> DeclRefExpr
-#-----| true -> GuardStmt
+#-----| false -> error1
+#-----| true -> guard ... else { ... }
-# 18| DeclRefExpr
-#-----| -> TypeExpr
+# 18| >=
+#-----| -> Int.Type
-# 18| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 18| Int.Type
+#-----| -> call to >=
-# 18| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 18| call to >=
+#-----| exception -> exit mightThrow (normal)
+#-----| -> x
-# 18| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 18| 0
+#-----| -> ... call to >= ...
-# 19| ThrowStmt
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 19| throw ...
+#-----| exception -> exit mightThrow (normal)
-# 19| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 19| MyError.Type
+#-----| -> call to ...
-# 19| DotSyntaxCallExpr
-#-----| -> ErasureExpr
+# 19| (Error) ...
+#-----| -> throw ...
-# 19| ErasureExpr
-#-----| -> ThrowStmt
+# 19| (TBD (ExistentialType)) ...
+#-----| -> throw ...
-# 19| DeclRefExpr
-#-----| -> TypeExpr
+# 19| call to ...
+#-----| -> (Error) ...
+#-----| -> (TBD (ExistentialType)) ...
-# 21| GuardStmt
-#-----| -> DeclRefExpr
+# 19| error1
+#-----| -> MyError.Type
-# 21| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 21| guard ... else { ... }
+#-----| -> <=
-# 21| BinaryExpr
+# 21| x
+#-----| -> 0
+
+# 21| ... call to <= ...
#-----| -> StmtCondition
# 21| StmtCondition
-#-----| true -> exit ConcreteFuncDecl (normal)
-#-----| false -> DeclRefExpr
+#-----| true -> exit mightThrow (normal)
+#-----| false -> error3
-# 21| DeclRefExpr
-#-----| -> TypeExpr
+# 21| <=
+#-----| -> Int.Type
-# 21| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 21| Int.Type
+#-----| -> call to <=
-# 21| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 21| call to <=
+#-----| exception -> exit mightThrow (normal)
+#-----| -> x
-# 21| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 21| 0
+#-----| -> ... call to <= ...
-# 22| ThrowStmt
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 22| throw ...
+#-----| exception -> exit mightThrow (normal)
-# 22| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 22| MyError.Type
+#-----| -> call to ...
-# 22| DotSyntaxCallExpr
-#-----| -> DeclRefExpr
+# 22| call to ...
+#-----| -> +
-# 22| CallExpr
-#-----| -> ErasureExpr
+# 22| (Error) ...
+#-----| -> throw ...
-# 22| ErasureExpr
-#-----| -> ThrowStmt
+# 22| (TBD (ExistentialType)) ...
+#-----| -> throw ...
-# 22| DeclRefExpr
-#-----| -> TypeExpr
+# 22| call to ...
+#-----| -> (Error) ...
+#-----| -> (TBD (ExistentialType)) ...
-# 22| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 22| error3
+#-----| -> MyError.Type
-# 22| BinaryExpr
-#-----| -> CallExpr
+# 22| x
+#-----| -> 1
-# 22| DeclRefExpr
-#-----| -> TypeExpr
+# 22| ... call to + ...
+#-----| -> call to ...
-# 22| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 22| +
+#-----| -> Int.Type
-# 22| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 22| Int.Type
+#-----| -> call to +
-# 22| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 22| call to +
+#-----| exception -> exit mightThrow (normal)
+#-----| -> x
-# 26| enter ConcreteFuncDecl
-#-----| -> DoCatchStmt
+# 22| 1
+#-----| -> ... call to + ...
-# 26| exit ConcreteFuncDecl
+# 26| enter tryCatch
+#-----| -> do { ... } catch { ... }
-# 26| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 26| exit tryCatch
-# 27| DoCatchStmt
-#-----| -> DeclRefExpr
+# 26| exit tryCatch (normal)
+#-----| -> exit tryCatch
-# 28| TryExpr
-#-----| -> DeclRefExpr
+# 27| do { ... } catch { ... }
+#-----| -> mightThrow
-# 28| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 28| try ...
+#-----| -> print
-# 28| CallExpr
-#-----| -> TryExpr
-#-----| exception -> CaseStmt
+# 28| mightThrow
+#-----| -> 0
-# 28| IntegerLiteralExpr
-#-----| -> CallExpr
+# 28| call to mightThrow
+#-----| -> try ...
+#-----| exception -> case ...
-# 29| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 28| 0
+#-----| -> call to mightThrow
-# 29| CallExpr
-#-----| exception -> CaseStmt
+# 29| print
+#-----| -> Did not throw.
-# 29| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 29| call to print
+#-----| exception -> case ...
-# 29| DefaultArgumentExpr
-#-----| -> CallExpr
+# 29| default separator
+#-----| -> default terminator
-# 29| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 29| default terminator
+#-----| -> call to print
-# 29| ErasureExpr
-#-----| -> ArrayExpr
+# 29| (Any) ...
+#-----| -> [...]
-# 29| StringLiteralExpr
-#-----| -> ErasureExpr
+# 29| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 29| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 29| Did not throw.
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 33| CaseStmt
-#-----| -> CaseLabelItem
+# 29| [...]
+#-----| -> default separator
-# 33| CaseLabelItem
-#-----| -> EnumElementPattern
+# 29| [...]
+#-----| -> [...]
-# 33| IsPattern
-#-----| no-match -> CaseLabelItem
-#-----| match -> IntegerLiteralExpr
+# 33| case ...
+#-----| -> ... is ...
-# 33| EnumElementPattern
-#-----| match -> IsPattern
+# 33| ... is ...
+#-----| -> .error1
-# 33| IsPattern
-#-----| match -> IntegerLiteralExpr
-#-----| no-match -> CaseStmt
-#-----| no-match -> IntegerLiteralExpr
+# 33| ... is ...
+#-----| no-match -> ... is ...
+#-----| match -> 0
-# 33| EnumElementPattern
-#-----| match -> IsPattern
+# 33| .error1
+#-----| no-match -> ... is ...
-# 33| CaseLabelItem
-#-----| -> EnumElementPattern
+# 33| ... is ...
+#-----| match -> 0
+#-----| no-match -> case ...
-# 34| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 33| .error2
+#-----| no-match -> ... is ...
-# 34| IntegerLiteralExpr
-#-----| -> ReturnStmt
+# 33| ... is ...
+#-----| -> .error2
-# 35| CaseStmt
-#-----| -> CaseLabelItem
+# 34| return ...
+#-----| return -> exit tryCatch (normal)
-# 35| CaseLabelItem
-#-----| -> EnumElementPattern
+# 34| 0
+#-----| -> return ...
-# 35| IsPattern
-#-----| match -> DeclRefExpr
-#-----| no-match -> CaseStmt
-#-----| no-match -> IntegerLiteralExpr
+# 35| case ...
+#-----| -> ... is ...
-# 35| EnumElementPattern
-#-----| no-match -> IsPattern
-#-----| match -> TuplePattern
+# 35| ... is ...
+#-----| match -> withParam
+#-----| no-match -> case ...
-# 35| TuplePattern
-#-----| -> NamedPattern
+# 35| ... is ...
+#-----| -> .error3(...)
-# 35| BindingPattern
-#-----| match -> IsPattern
+# 35| .error3(...)
+#-----| no-match -> ... is ...
+#-----| match -> (...)
-# 35| NamedPattern
-#-----| match -> BindingPattern
+# 35| (...)
+#-----| -> withParam
-# 36| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 35| let ...
+#-----| no-match -> ... is ...
-# 36| DeclRefExpr
-#-----| -> ReturnStmt
+# 35| withParam
+#-----| match -> let ...
-# 37| CaseStmt
-#-----| -> CaseLabelItem
+# 36| return ...
+#-----| return -> exit tryCatch (normal)
-# 37| CaseLabelItem
+# 36| withParam
+#-----| -> return ...
+
+# 37| case ...
+#-----| -> ... is ...
+
+# 37| ... is ...
#-----| -> TBD (SimpleIdentTypeRepr)
-# 37| IsPattern
-#-----| match -> DeclRefExpr
-#-----| no-match -> CaseStmt
-#-----| no-match -> IntegerLiteralExpr
+# 37| ... is ...
+#-----| match -> print
+#-----| no-match -> case ...
# 37| TBD (SimpleIdentTypeRepr)
-#-----| -> IsPattern
+#-----| -> ... is ...
-# 38| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 38| print
+#-----| -> MyError
-# 38| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> IntegerLiteralExpr
+# 38| call to print
+#-----| exception -> exit tryCatch (normal)
+#-----| -> 0
-# 38| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 38| default separator
+#-----| -> default terminator
-# 38| DefaultArgumentExpr
-#-----| -> CallExpr
+# 38| default terminator
+#-----| -> call to print
-# 38| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 38| (Any) ...
+#-----| -> [...]
-# 38| ErasureExpr
-#-----| -> ArrayExpr
+# 38| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 38| StringLiteralExpr
-#-----| -> ErasureExpr
+# 38| MyError
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 38| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 38| [...]
+#-----| -> default separator
-# 39| CaseStmt
-#-----| -> CaseLabelItem
+# 38| [...]
+#-----| -> [...]
-# 39| BindingPattern
-#-----| match -> DeclRefExpr
-#-----| no-match -> IntegerLiteralExpr
+# 39| case ...
+#-----| -> let ...
-# 39| CaseLabelItem
-#-----| -> NamedPattern
+# 39| error
+#-----| match -> let ...
-# 39| NamedPattern
-#-----| match -> BindingPattern
+# 39| let ...
+#-----| match -> print
+#-----| no-match -> 0
-# 40| DeclRefExpr
-#-----| -> InterpolatedStringLiteralExpr
+# 39| let ...
+#-----| -> error
-# 40| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> IntegerLiteralExpr
+# 40| print
+#-----| -> "..."
-# 40| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 40| call to print
+#-----| exception -> exit tryCatch (normal)
+#-----| -> 0
-# 40| DefaultArgumentExpr
-#-----| -> CallExpr
+# 40| default separator
+#-----| -> default terminator
-# 40| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 40| default terminator
+#-----| -> call to print
-# 40| ErasureExpr
-#-----| -> ArrayExpr
+# 40| "..."
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 40| InterpolatedStringLiteralExpr
-#-----| -> ErasureExpr
+# 40| (Any) ...
+#-----| -> [...]
-# 40| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 40| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 42| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 40| [...]
+#-----| -> default separator
-# 42| IntegerLiteralExpr
-#-----| -> ReturnStmt
+# 40| [...]
+#-----| -> [...]
-# 45| enter ConcreteFuncDecl
-#-----| -> ClosureExpr
+# 42| return ...
+#-----| return -> exit tryCatch (normal)
-# 45| exit ConcreteFuncDecl
+# 42| 0
+#-----| -> return ...
-# 45| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 45| enter createClosure1
+#-----| -> { ... }
-# 46| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 45| exit createClosure1
-# 46| ClosureExpr
-#-----| -> ReturnStmt
+# 45| exit createClosure1 (normal)
+#-----| -> exit createClosure1
-# 52| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 46| return ...
+#-----| return -> exit createClosure1 (normal)
-# 52| exit ConcreteFuncDecl
+# 46| { ... }
+#-----| -> return ...
-# 52| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 52| enter f
+#-----| -> +
-# 53| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 52| exit f
-# 53| DeclRefExpr
-#-----| -> DeclRefExpr
+# 52| exit f (normal)
+#-----| -> exit f
-# 53| BinaryExpr
-#-----| -> ReturnStmt
+# 53| return ...
+#-----| return -> exit f (normal)
-# 53| DeclRefExpr
-#-----| -> TypeExpr
+# 53| x
+#-----| -> y
-# 53| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 53| ... call to + ...
+#-----| -> return ...
-# 53| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 53| +
+#-----| -> Int.Type
-# 53| DeclRefExpr
-#-----| -> BinaryExpr
+# 53| Int.Type
+#-----| -> call to +
-# 58| enter ConcreteFuncDecl
-#-----| -> ClosureExpr
+# 53| call to +
+#-----| exception -> exit f (normal)
+#-----| -> x
-# 58| exit ConcreteFuncDecl
+# 53| y
+#-----| -> ... call to + ...
-# 58| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 58| enter createClosure3
+#-----| -> { ... }
-# 59| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 58| exit createClosure3
-# 59| ClosureExpr
-#-----| -> ReturnStmt
+# 58| exit createClosure3 (normal)
+#-----| -> exit createClosure3
-# 64| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 59| return ...
+#-----| return -> exit createClosure3 (normal)
-# 64| exit ConcreteFuncDecl
+# 59| { ... }
+#-----| -> return ...
-# 64| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 64| enter callClosures
+#-----| -> x1
-# 65| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 64| exit callClosures
-# 65| ConcreteVarDecl
-#-----| -> NamedPattern
+# 64| exit callClosures (normal)
+#-----| -> exit callClosures
-# 65| NamedPattern
-#-----| -> DeclRefExpr
+# 65| var ... = ...
+#-----| -> x1
-# 65| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 65| x1
+#-----| -> createClosure1
-# 65| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 65| x1
+#-----| -> x2
-# 65| CallExpr
-#-----| -> PatternBindingDecl
+# 65| createClosure1
+#-----| ->
-# 65| StringLiteralExpr
-#-----| -> CallExpr
+# 65| call to createClosure1
+#-----| exception -> exit callClosures (normal)
+#-----| -> call to ...
-# 66| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 65| call to ...
+#-----| -> var ... = ...
-# 66| ConcreteVarDecl
-#-----| -> NamedPattern
+# 65|
+#-----| -> call to createClosure1
-# 66| NamedPattern
-#-----| -> DeclRefExpr
+# 66| var ... = ...
+#-----| -> x2
-# 66| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 66| x2
+#-----| -> createClosure2
-# 66| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> IntegerLiteralExpr
+# 66| x2
+#-----| -> x3
-# 66| CallExpr
-#-----| -> PatternBindingDecl
+# 66| createClosure2
+#-----| -> 0
-# 66| IntegerLiteralExpr
-#-----| -> CallExpr
+# 66| call to createClosure2
+#-----| exception -> exit callClosures (normal)
+#-----| -> 10
-# 66| IntegerLiteralExpr
-#-----| -> CallExpr
+# 66| call to ...
+#-----| -> var ... = ...
-# 67| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 66| 0
+#-----| -> call to createClosure2
-# 67| ConcreteVarDecl
-#-----| -> exit ConcreteFuncDecl (normal)
+# 66| 10
+#-----| -> call to ...
-# 67| NamedPattern
-#-----| -> DeclRefExpr
+# 67| var ... = ...
+#-----| -> x3
-# 67| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 67| x3
+#-----| -> createClosure3
-# 67| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> IntegerLiteralExpr
+# 67| x3
+#-----| -> exit callClosures (normal)
-# 67| CallExpr
-#-----| -> PatternBindingDecl
+# 67| createClosure3
+#-----| -> 0
-# 67| IntegerLiteralExpr
-#-----| -> CallExpr
+# 67| call to createClosure3
+#-----| exception -> exit callClosures (normal)
+#-----| -> 10
-# 67| IntegerLiteralExpr
-#-----| -> CallExpr
+# 67| call to ...
+#-----| -> var ... = ...
-# 70| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 67| 0
+#-----| -> call to createClosure3
-# 70| exit ConcreteFuncDecl
+# 67| 10
+#-----| -> call to ...
-# 70| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 70| enter maybeParseInt
+#-----| -> n
-# 71| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 70| exit maybeParseInt
-# 71| ConcreteVarDecl
-#-----| -> DeclRefExpr
+# 70| exit maybeParseInt (normal)
+#-----| -> exit maybeParseInt
-# 71| NamedPattern
-#-----| -> TypedPattern
+# 71| var ... = ...
+#-----| -> n
-# 71| TypedPattern
-#-----| -> DeclRefExpr
+# 71| n
+#-----| -> ... as ...
-# 71| ConstructorRefCallExpr
-#-----| -> DeclRefExpr
+# 71| n
+#-----| -> n
-# 71| DeclRefExpr
-#-----| -> TypeExpr
+# 71| ... as ...
+#-----| -> deinit
-# 71| TypeExpr
-#-----| -> ConstructorRefCallExpr
+# 71| Int.Type
+#-----| -> call to ...
-# 71| CallExpr
-#-----| -> PatternBindingDecl
+# 71| call to ...
+#-----| -> s
-# 71| DeclRefExpr
-#-----| -> CallExpr
+# 71| deinit
+#-----| -> Int.Type
-# 72| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 71| call to ...
+#-----| -> var ... = ...
-# 72| DeclRefExpr
-#-----| -> LoadExpr
+# 71| s
+#-----| -> call to ...
-# 72| LoadExpr
-#-----| -> ReturnStmt
+# 72| return ...
+#-----| return -> exit maybeParseInt (normal)
-# 75| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 72| (Int?) ...
+#-----| -> return ...
-# 75| exit ConcreteFuncDecl
+# 72| n
+#-----| -> (Int?) ...
-# 75| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 75| enter forceAndBackToOptional
+#-----| -> nBang
-# 76| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 75| exit forceAndBackToOptional
-# 76| ConcreteVarDecl
-#-----| -> NamedPattern
+# 75| exit forceAndBackToOptional (normal)
+#-----| -> exit forceAndBackToOptional
-# 76| NamedPattern
-#-----| -> DeclRefExpr
+# 76| var ... = ...
+#-----| -> nBang
-# 76| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 76| nBang
+#-----| -> maybeParseInt
-# 76| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> ForceValueExpr
+# 76| nBang
+#-----| -> n
-# 76| ForceValueExpr
-#-----| -> PatternBindingDecl
+# 76| maybeParseInt
+#-----| -> 42
-# 76| StringLiteralExpr
-#-----| -> CallExpr
+# 76| call to maybeParseInt
+#-----| exception -> exit forceAndBackToOptional (normal)
+#-----| -> ...!
-# 77| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 76| ...!
+#-----| -> var ... = ...
-# 77| ConcreteVarDecl
-#-----| -> DeclRefExpr
+# 76| 42
+#-----| -> call to maybeParseInt
-# 77| NamedPattern
-#-----| -> DeclRefExpr
+# 77| var ... = ...
+#-----| -> n
-# 77| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 77| n
+#-----| -> maybeParseInt
-# 77| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> PatternBindingDecl
+# 77| n
+#-----| -> +
-# 77| StringLiteralExpr
-#-----| -> CallExpr
+# 77| maybeParseInt
+#-----| -> 42
-# 78| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 77| call to maybeParseInt
+#-----| exception -> exit forceAndBackToOptional (normal)
+#-----| -> var ... = ...
-# 78| DeclRefExpr
-#-----| -> LoadExpr
+# 77| 42
+#-----| -> call to maybeParseInt
-# 78| LoadExpr
-#-----| -> DeclRefExpr
+# 78| return ...
+#-----| return -> exit forceAndBackToOptional (normal)
-# 78| BinaryExpr
-#-----| -> InjectIntoOptionalExpr
+# 78| (Int) ...
+#-----| -> n
-# 78| InjectIntoOptionalExpr
-#-----| -> ReturnStmt
+# 78| nBang
+#-----| -> (Int) ...
-# 78| DeclRefExpr
-#-----| -> TypeExpr
+# 78| (Int?) ...
+#-----| -> return ...
-# 78| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 78| ... call to + ...
+#-----| -> (Int?) ...
-# 78| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 78| +
+#-----| -> Int.Type
-# 78| DeclRefExpr
-#-----| -> LoadExpr
+# 78| Int.Type
+#-----| -> call to +
-# 78| LoadExpr
-#-----| -> ForceValueExpr
+# 78| call to +
+#-----| exception -> exit forceAndBackToOptional (normal)
+#-----| -> nBang
-# 78| ForceValueExpr
-#-----| -> BinaryExpr
+# 78| (Int?) ...
+#-----| -> ...!
-# 81| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 78| n
+#-----| -> (Int?) ...
-# 82| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 78| ...!
+#-----| -> ... call to + ...
-# 82| ConcreteVarDecl
+# 81| enter testInOut
+#-----| -> temp
-# 82| NamedPattern
-#-----| -> IntegerLiteralExpr
+# 82| var ... = ...
+#-----| -> temp
-# 82| IntegerLiteralExpr
-#-----| -> PatternBindingDecl
+# 82| temp
+#-----| -> 10
-# 84| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 82| temp
-# 84| exit ConcreteFuncDecl
+# 82| 10
+#-----| -> var ... = ...
-# 84| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 84| enter add
+#-----| -> a
-# 85| DeclRefExpr
-#-----| -> DeclRefExpr
+# 84| exit add
-# 85| AssignExpr
-#-----| -> exit ConcreteFuncDecl (normal)
+# 84| exit add (normal)
+#-----| -> exit add
-# 85| DeclRefExpr
-#-----| -> LoadExpr
+# 85| a
+#-----| -> +
-# 85| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 85| ... = ...
+#-----| -> exit add (normal)
-# 85| BinaryExpr
-#-----| -> AssignExpr
+# 85| (Int) ...
+#-----| -> 1
-# 85| DeclRefExpr
-#-----| -> TypeExpr
+# 85| a
+#-----| -> (Int) ...
-# 85| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 85| ... call to + ...
+#-----| -> ... = ...
-# 85| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 85| +
+#-----| -> Int.Type
-# 85| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 85| Int.Type
+#-----| -> call to +
-# 88| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 85| call to +
+#-----| exception -> exit add (normal)
+#-----| -> a
-# 88| exit ConcreteFuncDecl
+# 85| 1
+#-----| -> ... call to + ...
-# 88| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 88| enter addOptional
+#-----| -> a
-# 89| DeclRefExpr
-#-----| -> NilLiteralExpr
+# 88| exit addOptional
-# 89| AssignExpr
-#-----| -> exit ConcreteFuncDecl (normal)
+# 88| exit addOptional (normal)
+#-----| -> exit addOptional
-# 89| NilLiteralExpr
-#-----| -> AssignExpr
+# 89| a
+#-----| -> nil
-# 99| enter AccessorDecl
+# 89| ... = ...
+#-----| -> exit addOptional (normal)
-# 99| exit AccessorDecl
+# 89| nil
+#-----| -> ... = ...
-# 99| exit AccessorDecl (normal)
-#-----| -> exit AccessorDecl
+# 99| enter get
-# 100| enter ConstructorDecl
-#-----| -> DeclRefExpr
+# 99| exit get
-# 100| exit ConstructorDecl
+# 99| exit get (normal)
+#-----| -> exit get
-# 100| exit ConstructorDecl (normal)
-#-----| -> exit ConstructorDecl
+# 100| enter deinit
+#-----| -> self
-# 101| DeclRefExpr
-#-----| -> MemberRefExpr
+# 100| exit deinit
-# 101| MemberRefExpr
-#-----| -> DeclRefExpr
+# 100| exit deinit (normal)
+#-----| -> exit deinit
-# 101| AssignExpr
-#-----| -> ReturnStmt
+# 101| .myInt
+#-----| -> n
-# 101| DeclRefExpr
-#-----| -> AssignExpr
+# 101| self
+#-----| -> .myInt
-# 102| ReturnStmt
-#-----| return -> exit ConstructorDecl (normal)
+# 101| ... = ...
+#-----| -> return
-# 104| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 101| n
+#-----| -> ... = ...
-# 104| exit ConcreteFuncDecl
+# 102| return
+#-----| return -> exit deinit (normal)
-# 104| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 104| enter getMyInt
+#-----| -> self
-# 105| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 104| exit getMyInt
-# 105| DeclRefExpr
-#-----| -> MemberRefExpr
+# 104| exit getMyInt (normal)
+#-----| -> exit getMyInt
-# 105| MemberRefExpr
-#-----| -> ReturnStmt
+# 105| return ...
+#-----| return -> exit getMyInt (normal)
-# 109| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 105| getter for .myInt
+#-----| -> return ...
-# 109| exit ConcreteFuncDecl
+# 105| self
+#-----| -> getter for .myInt
-# 109| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 109| enter testMemberRef
+#-----| -> c
-# 110| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 109| exit testMemberRef
-# 110| ConcreteVarDecl
-#-----| -> NamedPattern
+# 109| exit testMemberRef (normal)
+#-----| -> exit testMemberRef
-# 110| NamedPattern
-#-----| -> DeclRefExpr
+# 110| var ... = ...
+#-----| -> c
-# 110| ConstructorRefCallExpr
-#-----| -> IntegerLiteralExpr
+# 110| c
+#-----| -> deinit
-# 110| DeclRefExpr
-#-----| -> TypeExpr
+# 110| c
+#-----| -> n1
-# 110| TypeExpr
-#-----| -> ConstructorRefCallExpr
+# 110| C.Type
+#-----| -> call to ...
-# 110| CallExpr
-#-----| -> PatternBindingDecl
+# 110| call to ...
+#-----| -> 42
-# 110| IntegerLiteralExpr
-#-----| -> CallExpr
+# 110| deinit
+#-----| -> C.Type
-# 111| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 110| call to ...
+#-----| -> var ... = ...
-# 111| ConcreteVarDecl
-#-----| -> NamedPattern
+# 110| 42
+#-----| -> call to ...
-# 111| NamedPattern
-#-----| -> DeclRefExpr
+# 111| var ... = ...
+#-----| -> n1
-# 111| DeclRefExpr
-#-----| -> MemberRefExpr
+# 111| n1
+#-----| -> c
-# 111| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 111| n1
+#-----| -> n2
-# 112| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 111| c
+#-----| -> getter for .myInt
-# 112| ConcreteVarDecl
-#-----| -> NamedPattern
+# 111| getter for .myInt
+#-----| -> var ... = ...
-# 112| NamedPattern
+# 112| var ... = ...
+#-----| -> n2
+
+# 112| n2
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
+# 112| n2
+#-----| -> n3
+
+# 112| .self
+#-----| -> getter for .myInt
+
# 112| TBD (DotSelfExpr)
-#-----| -> MemberRefExpr
+#-----| -> getter for .myInt
-# 112| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 112| getter for .myInt
+#-----| -> var ... = ...
-# 113| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 113| var ... = ...
+#-----| -> n3
-# 113| ConcreteVarDecl
-#-----| -> NamedPattern
+# 113| n3
+#-----| -> getMyInt
-# 113| NamedPattern
-#-----| -> DeclRefExpr
+# 113| n3
+#-----| -> n4
-# 113| DeclRefExpr
-#-----| -> DotSyntaxCallExpr
+# 113| c
+#-----| -> call to getMyInt
-# 113| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 113| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 113| CallExpr
-#-----| -> PatternBindingDecl
+# 113| call to ...
+#-----| -> var ... = ...
-# 113| DeclRefExpr
-#-----| -> DeclRefExpr
+# 113| getMyInt
+#-----| -> c
-# 114| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 114| var ... = ...
+#-----| -> n4
-# 114| ConcreteVarDecl
-#-----| -> NamedPattern
+# 114| n4
+#-----| -> getMyInt
-# 114| NamedPattern
-#-----| -> DeclRefExpr
+# 114| n4
+#-----| -> n5
+
+# 114| .self
+#-----| -> call to getMyInt
# 114| TBD (DotSelfExpr)
-#-----| -> DotSyntaxCallExpr
+#-----| -> call to getMyInt
-# 114| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 114| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 114| CallExpr
-#-----| -> PatternBindingDecl
+# 114| call to ...
+#-----| -> var ... = ...
-# 114| DeclRefExpr
+# 114| getMyInt
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 116| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 116| var ... = ...
+#-----| -> n5
-# 116| ConcreteVarDecl
-#-----| -> NamedPattern
+# 116| n5
+#-----| -> param
-# 116| NamedPattern
-#-----| -> DeclRefExpr
+# 116| n5
+#-----| -> n6
-# 116| DeclRefExpr
-#-----| -> MemberRefExpr
+# 116| param
+#-----| -> getter for .myInt
-# 116| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 116| getter for .myInt
+#-----| -> var ... = ...
-# 117| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 117| var ... = ...
+#-----| -> n6
-# 117| ConcreteVarDecl
-#-----| -> NamedPattern
-
-# 117| NamedPattern
+# 117| n6
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
+# 117| n6
+#-----| -> n7
+
+# 117| .self
+#-----| -> getter for .myInt
+
# 117| TBD (DotSelfExpr)
-#-----| -> MemberRefExpr
+#-----| -> getter for .myInt
-# 117| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 117| getter for .myInt
+#-----| -> var ... = ...
-# 118| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 118| var ... = ...
+#-----| -> n7
-# 118| ConcreteVarDecl
-#-----| -> NamedPattern
+# 118| n7
+#-----| -> getMyInt
-# 118| NamedPattern
-#-----| -> DeclRefExpr
+# 118| n7
+#-----| -> n8
-# 118| DeclRefExpr
-#-----| -> DotSyntaxCallExpr
+# 118| param
+#-----| -> call to getMyInt
-# 118| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 118| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 118| CallExpr
-#-----| -> PatternBindingDecl
+# 118| call to ...
+#-----| -> var ... = ...
-# 118| DeclRefExpr
-#-----| -> DeclRefExpr
+# 118| getMyInt
+#-----| -> param
-# 119| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 119| var ... = ...
+#-----| -> n8
-# 119| ConcreteVarDecl
-#-----| -> NamedPattern
+# 119| n8
+#-----| -> getMyInt
-# 119| NamedPattern
-#-----| -> DeclRefExpr
+# 119| n8
+#-----| -> n9
+
+# 119| .self
+#-----| -> call to getMyInt
# 119| TBD (DotSelfExpr)
-#-----| -> DotSyntaxCallExpr
+#-----| -> call to getMyInt
-# 119| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 119| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 119| CallExpr
-#-----| -> PatternBindingDecl
+# 119| call to ...
+#-----| -> var ... = ...
-# 119| DeclRefExpr
+# 119| getMyInt
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 121| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 121| var ... = ...
+#-----| -> n9
-# 121| ConcreteVarDecl
-#-----| -> NamedPattern
+# 121| n9
+#-----| -> inoutParam
-# 121| NamedPattern
-#-----| -> DeclRefExpr
+# 121| n9
+#-----| -> n10
-# 121| DeclRefExpr
-#-----| -> LoadExpr
+# 121| (C) ...
+#-----| -> getter for .myInt
-# 121| LoadExpr
-#-----| -> MemberRefExpr
+# 121| inoutParam
+#-----| -> (C) ...
-# 121| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 121| getter for .myInt
+#-----| -> var ... = ...
-# 122| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 122| var ... = ...
+#-----| -> n10
-# 122| ConcreteVarDecl
-#-----| -> NamedPattern
-
-# 122| NamedPattern
+# 122| n10
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 122| LoadExpr
-#-----| -> MemberRefExpr
+# 122| n10
+#-----| -> n11
+
+# 122| (C) ...
+#-----| -> getter for .myInt
+
+# 122| .self
+#-----| -> (C) ...
# 122| TBD (DotSelfExpr)
-#-----| -> LoadExpr
+#-----| -> (C) ...
-# 122| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 122| getter for .myInt
+#-----| -> var ... = ...
-# 123| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 123| var ... = ...
+#-----| -> n11
-# 123| ConcreteVarDecl
-#-----| -> NamedPattern
+# 123| n11
+#-----| -> getMyInt
-# 123| NamedPattern
-#-----| -> DeclRefExpr
+# 123| n11
+#-----| -> n12
-# 123| DeclRefExpr
-#-----| -> LoadExpr
+# 123| (C) ...
+#-----| -> call to getMyInt
-# 123| LoadExpr
-#-----| -> DotSyntaxCallExpr
+# 123| inoutParam
+#-----| -> (C) ...
-# 123| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 123| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 123| CallExpr
-#-----| -> PatternBindingDecl
+# 123| call to ...
+#-----| -> var ... = ...
-# 123| DeclRefExpr
-#-----| -> DeclRefExpr
+# 123| getMyInt
+#-----| -> inoutParam
-# 124| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 124| var ... = ...
+#-----| -> n12
-# 124| ConcreteVarDecl
-#-----| -> NamedPattern
+# 124| n12
+#-----| -> getMyInt
-# 124| NamedPattern
-#-----| -> DeclRefExpr
+# 124| n12
+#-----| -> n13
-# 124| LoadExpr
-#-----| -> DotSyntaxCallExpr
+# 124| (C) ...
+#-----| -> call to getMyInt
+
+# 124| .self
+#-----| -> (C) ...
# 124| TBD (DotSelfExpr)
-#-----| -> LoadExpr
+#-----| -> (C) ...
-# 124| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 124| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 124| CallExpr
-#-----| -> PatternBindingDecl
+# 124| call to ...
+#-----| -> var ... = ...
-# 124| DeclRefExpr
+# 124| getMyInt
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 126| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 126| var ... = ...
+#-----| -> n13
-# 126| ConcreteVarDecl
-#-----| -> NamedPattern
+# 126| n13
+#-----| -> opt
-# 126| NamedPattern
-#-----| -> DeclRefExpr
+# 126| n13
+#-----| -> n14
-# 126| DeclRefExpr
-#-----| -> ForceValueExpr
+# 126| opt
+#-----| -> ...!
-# 126| ForceValueExpr
-#-----| -> MemberRefExpr
+# 126| ...!
+#-----| -> getter for .myInt
-# 126| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 126| getter for .myInt
+#-----| -> var ... = ...
-# 127| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 127| var ... = ...
+#-----| -> n14
-# 127| ConcreteVarDecl
-#-----| -> NamedPattern
-
-# 127| NamedPattern
+# 127| n14
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
+# 127| n14
+#-----| -> n15
+
+# 127| .self
+#-----| -> getter for .myInt
+
# 127| TBD (DotSelfExpr)
-#-----| -> MemberRefExpr
+#-----| -> getter for .myInt
-# 127| MemberRefExpr
-#-----| -> PatternBindingDecl
+# 127| getter for .myInt
+#-----| -> var ... = ...
-# 128| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 128| var ... = ...
+#-----| -> n15
-# 128| ConcreteVarDecl
-#-----| -> NamedPattern
+# 128| n15
+#-----| -> getMyInt
-# 128| NamedPattern
-#-----| -> DeclRefExpr
+# 128| n15
+#-----| -> n16
-# 128| DeclRefExpr
-#-----| -> ForceValueExpr
+# 128| opt
+#-----| -> ...!
-# 128| ForceValueExpr
-#-----| -> DotSyntaxCallExpr
+# 128| ...!
+#-----| -> call to getMyInt
-# 128| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 128| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 128| CallExpr
-#-----| -> PatternBindingDecl
+# 128| call to ...
+#-----| -> var ... = ...
-# 128| DeclRefExpr
-#-----| -> DeclRefExpr
+# 128| getMyInt
+#-----| -> opt
-# 129| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 129| var ... = ...
+#-----| -> n16
-# 129| ConcreteVarDecl
-#-----| -> NamedPattern
+# 129| n16
+#-----| -> getMyInt
-# 129| NamedPattern
-#-----| -> DeclRefExpr
+# 129| n16
+#-----| -> n17
+
+# 129| .self
+#-----| -> call to getMyInt
# 129| TBD (DotSelfExpr)
-#-----| -> DotSyntaxCallExpr
+#-----| -> call to getMyInt
-# 129| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 129| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 129| CallExpr
-#-----| -> PatternBindingDecl
+# 129| call to ...
+#-----| -> var ... = ...
-# 129| DeclRefExpr
+# 129| getMyInt
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 131| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 131| var ... = ...
+#-----| -> n17
-# 131| ConcreteVarDecl
-#-----| -> NamedPattern
+# 131| n17
+#-----| -> opt
-# 131| NamedPattern
-#-----| -> DeclRefExpr
+# 131| n17
+#-----| -> n18
-# 131| DeclRefExpr
-#-----| -> BindOptionalExpr
+# 131| opt
+#-----| -> ...?
-# 131| BindOptionalExpr
-#-----| -> MemberRefExpr
+# 131| ...?
+#-----| -> getter for .myInt
-# 131| InjectIntoOptionalExpr
+# 131| (Int?) ...
#-----| -> OptionalEvaluationExpr
-# 131| MemberRefExpr
-#-----| -> InjectIntoOptionalExpr
-
# 131| OptionalEvaluationExpr
-#-----| -> PatternBindingDecl
+#-----| -> var ... = ...
-# 132| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 131| getter for .myInt
+#-----| -> (Int?) ...
-# 132| ConcreteVarDecl
-#-----| -> NamedPattern
+# 132| var ... = ...
+#-----| -> n18
-# 132| NamedPattern
+# 132| n18
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 132| TBD (DotSelfExpr)
-#-----| -> MemberRefExpr
+# 132| n18
+#-----| -> n19
-# 132| InjectIntoOptionalExpr
+# 132| .self
+#-----| -> getter for .myInt
+
+# 132| TBD (DotSelfExpr)
+#-----| -> getter for .myInt
+
+# 132| (Int?) ...
#-----| -> OptionalEvaluationExpr
-# 132| MemberRefExpr
-#-----| -> InjectIntoOptionalExpr
-
# 132| OptionalEvaluationExpr
-#-----| -> PatternBindingDecl
+#-----| -> var ... = ...
-# 133| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 132| getter for .myInt
+#-----| -> (Int?) ...
-# 133| ConcreteVarDecl
-#-----| -> NamedPattern
+# 133| var ... = ...
+#-----| -> n19
-# 133| NamedPattern
-#-----| -> DeclRefExpr
+# 133| n19
+#-----| -> getMyInt
-# 133| DeclRefExpr
-#-----| -> BindOptionalExpr
+# 133| n19
+#-----| -> n20
-# 133| BindOptionalExpr
-#-----| -> DotSyntaxCallExpr
+# 133| opt
+#-----| -> ...?
-# 133| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 133| ...?
+#-----| -> call to getMyInt
-# 133| CallExpr
-#-----| -> InjectIntoOptionalExpr
+# 133| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 133| InjectIntoOptionalExpr
+# 133| (Int?) ...
#-----| -> OptionalEvaluationExpr
# 133| OptionalEvaluationExpr
-#-----| -> PatternBindingDecl
+#-----| -> var ... = ...
-# 133| DeclRefExpr
-#-----| -> DeclRefExpr
+# 133| call to ...
+#-----| -> (Int?) ...
-# 134| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 133| getMyInt
+#-----| -> opt
-# 134| ConcreteVarDecl
-#-----| -> exit ConcreteFuncDecl (normal)
+# 134| var ... = ...
+#-----| -> n20
-# 134| NamedPattern
-#-----| -> DeclRefExpr
+# 134| n20
+#-----| -> getMyInt
+
+# 134| n20
+#-----| -> exit testMemberRef (normal)
+
+# 134| .self
+#-----| -> call to getMyInt
# 134| TBD (DotSelfExpr)
-#-----| -> DotSyntaxCallExpr
+#-----| -> call to getMyInt
-# 134| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 134| call to getMyInt
+#-----| exception -> exit testMemberRef (normal)
+#-----| -> call to ...
-# 134| CallExpr
-#-----| -> InjectIntoOptionalExpr
-
-# 134| InjectIntoOptionalExpr
+# 134| (Int?) ...
#-----| -> OptionalEvaluationExpr
# 134| OptionalEvaluationExpr
-#-----| -> PatternBindingDecl
+#-----| -> var ... = ...
-# 134| DeclRefExpr
+# 134| call to ...
+#-----| -> (Int?) ...
+
+# 134| getMyInt
+#-----| -> .self
#-----| -> TBD (DotSelfExpr)
-# 137| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 137| enter patterns
+#-----| -> ...
-# 137| exit ConcreteFuncDecl
+# 137| exit patterns
-# 137| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 137| exit patterns (normal)
+#-----| -> exit patterns
-# 138| ForEachStmt
-#-----| non-empty -> AnyPattern
-#-----| empty -> SwitchStmt
+# 138| for ... in ... { ... }
+#-----| non-empty -> _
+#-----| empty -> switch x { ... }
-# 138| AnyPattern
-#-----| -> BraceStmt
+# 138| _
+#-----| -> { ... }
-# 138| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 138| 0
+#-----| -> 10
-# 138| BinaryExpr
-#-----| -> ForEachStmt
+# 138| ... call to ... ...
+#-----| -> for ... in ... { ... }
-# 138| DeclRefExpr
-#-----| -> TypeExpr
+# 138| ...
+#-----| -> Int.Type
-# 138| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> IntegerLiteralExpr
+# 138| Int.Type
+#-----| -> call to ...
-# 138| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 138| call to ...
+#-----| exception -> exit patterns (normal)
+#-----| -> 0
-# 138| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 138| 10
+#-----| -> ... call to ... ...
-# 138| BraceStmt
-#-----| -> ForEachStmt
+# 138| { ... }
+#-----| -> for ... in ... { ... }
-# 140| SwitchStmt
-#-----| -> DeclRefExpr
+# 140| switch x { ... }
+#-----| -> x
-# 140| DeclRefExpr
-#-----| -> CaseStmt
+# 140| x
+#-----| -> case ...
-# 141| CaseStmt
-#-----| -> CaseLabelItem
+# 141| case ...
+#-----| -> 0
-# 141| CaseLabelItem
-#-----| -> IntegerLiteralExpr
+# 141| 0
+#-----| -> 0
-# 141| ExprPattern
-#-----| no-match -> CaseLabelItem
-#-----| match -> BooleanLiteralExpr
+# 141| 0
+#-----| no-match -> 1
+#-----| match -> true
-# 141| IntegerLiteralExpr
-#-----| -> ExprPattern
+# 141| 0
+#-----| -> 0
-# 141| CaseLabelItem
-#-----| -> IntegerLiteralExpr
+# 141| 1
+#-----| -> 1
-# 141| ExprPattern
-#-----| match -> BooleanLiteralExpr
-#-----| no-match -> CaseStmt
+# 141| 1
+#-----| match -> true
+#-----| no-match -> case ...
-# 141| IntegerLiteralExpr
-#-----| -> ExprPattern
+# 141| 1
+#-----| -> 1
-# 142| ReturnStmt
+# 142| return ...
-# 142| BooleanLiteralExpr
-#-----| -> ReturnStmt
+# 142| true
+#-----| -> return ...
-# 144| CaseStmt
-#-----| -> CaseLabelItem
+# 144| case ...
+#-----| -> x
-# 144| DeclRefExpr
-#-----| -> ExprPattern
+# 144| x
+#-----| match -> true
+#-----| no-match -> case ...
-# 144| ExprPattern
-#-----| match -> BooleanLiteralExpr
-#-----| no-match -> CaseStmt
+# 144| x
+#-----| -> x
-# 144| CaseLabelItem
-#-----| -> DeclRefExpr
+# 144| x
+#-----| -> x
-# 145| ReturnStmt
+# 145| return ...
-# 145| BooleanLiteralExpr
-#-----| -> ReturnStmt
+# 145| true
+#-----| -> return ...
-# 146| AnyPattern
-#-----| match -> BooleanLiteralExpr
+# 146| _
+#-----| -> _
-# 146| CaseLabelItem
-#-----| -> AnyPattern
+# 146| _
+#-----| match -> false
-# 146| CaseStmt
-#-----| -> CaseLabelItem
+# 146| case ...
+#-----| -> _
-# 147| ReturnStmt
+# 147| return ...
-# 147| BooleanLiteralExpr
-#-----| -> ReturnStmt
+# 147| false
+#-----| -> return ...
-# 163| enter ConcreteFuncDecl
-#-----| -> DeferStmt
+# 163| enter testDefer
+#-----| -> defer { ... }
-# 163| exit ConcreteFuncDecl
+# 163| exit testDefer
-# 163| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 163| exit testDefer (normal)
+#-----| -> exit testDefer
-# 165| DeferStmt
-#-----| -> DeferStmt
+# 165| defer { ... }
+#-----| -> defer { ... }
-# 166| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 166| print
+#-----| -> 4
-# 166| CallExpr
-#-----| -> exit ConcreteFuncDecl (normal)
+# 166| call to print
+#-----| -> exit testDefer (normal)
-# 166| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 166| default separator
+#-----| -> default terminator
-# 166| DefaultArgumentExpr
-#-----| -> CallExpr
+# 166| default terminator
+#-----| -> call to print
-# 166| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 166| (Any) ...
+#-----| -> [...]
-# 166| ErasureExpr
-#-----| -> ArrayExpr
+# 166| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 166| StringLiteralExpr
-#-----| -> ErasureExpr
+# 166| 4
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 166| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 166| [...]
+#-----| -> default separator
-# 169| DeferStmt
-#-----| -> DeferStmt
+# 166| [...]
+#-----| -> [...]
-# 170| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 169| defer { ... }
+#-----| -> defer { ... }
-# 170| CallExpr
-#-----| -> DeclRefExpr
+# 170| print
+#-----| -> 3
-# 170| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 170| call to print
+#-----| -> print
-# 170| DefaultArgumentExpr
-#-----| -> CallExpr
+# 170| default separator
+#-----| -> default terminator
-# 170| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 170| default terminator
+#-----| -> call to print
-# 170| ErasureExpr
-#-----| -> ArrayExpr
+# 170| (Any) ...
+#-----| -> [...]
-# 170| StringLiteralExpr
-#-----| -> ErasureExpr
+# 170| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 170| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 170| 3
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 173| DeferStmt
-#-----| -> DeclRefExpr
+# 170| [...]
+#-----| -> default separator
-# 174| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 170| [...]
+#-----| -> [...]
-# 174| CallExpr
-#-----| -> DeferStmt
+# 173| defer { ... }
+#-----| -> print
-# 174| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 174| print
+#-----| -> 1
-# 174| DefaultArgumentExpr
-#-----| -> CallExpr
+# 174| call to print
+#-----| -> defer { ... }
-# 174| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 174| default separator
+#-----| -> default terminator
-# 174| ErasureExpr
-#-----| -> ArrayExpr
+# 174| default terminator
+#-----| -> call to print
-# 174| StringLiteralExpr
-#-----| -> ErasureExpr
+# 174| (Any) ...
+#-----| -> [...]
-# 174| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 174| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 175| DeferStmt
-#-----| -> DeclRefExpr
+# 174| 1
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 176| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 174| [...]
+#-----| -> default separator
-# 176| CallExpr
-#-----| -> DeclRefExpr
+# 174| [...]
+#-----| -> [...]
-# 176| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 175| defer { ... }
+#-----| -> print
-# 176| DefaultArgumentExpr
-#-----| -> CallExpr
+# 176| print
+#-----| -> 2
-# 176| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 176| call to print
+#-----| -> print
-# 176| ErasureExpr
-#-----| -> ArrayExpr
+# 176| default separator
+#-----| -> default terminator
-# 176| StringLiteralExpr
-#-----| -> ErasureExpr
+# 176| default terminator
+#-----| -> call to print
-# 176| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 176| (Any) ...
+#-----| -> [...]
-# 181| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 176| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 181| exit ConcreteFuncDecl
+# 176| 2
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 181| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 176| [...]
+#-----| -> default separator
-# 182| IfStmt
-#-----| -> DeclRefExpr
+# 176| [...]
+#-----| -> [...]
-# 182| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 181| enter m1
+#-----| -> if ... then { ... } else { ... }
-# 182| BinaryExpr
+# 181| exit m1
+
+# 181| exit m1 (normal)
+#-----| -> exit m1
+
+# 182| if ... then { ... } else { ... }
+#-----| -> >
+
+# 182| x
+#-----| -> 2
+
+# 182| ... call to > ...
#-----| -> StmtCondition
# 182| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> IfStmt
+#-----| true -> print
+#-----| false -> if ... then { ... } else { ... }
-# 182| DeclRefExpr
-#-----| -> TypeExpr
+# 182| >
+#-----| -> Int.Type
-# 182| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 182| Int.Type
+#-----| -> call to >
-# 182| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 182| call to >
+#-----| exception -> exit m1 (normal)
+#-----| -> x
-# 182| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 182| 2
+#-----| -> ... call to > ...
-# 183| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 183| print
+#-----| -> x is greater than 2
-# 183| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 183| call to print
+#-----| exception -> exit m1 (normal)
-# 183| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 183| default separator
+#-----| -> default terminator
-# 183| DefaultArgumentExpr
-#-----| -> CallExpr
+# 183| default terminator
+#-----| -> call to print
-# 183| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 183| (Any) ...
+#-----| -> [...]
-# 183| ErasureExpr
-#-----| -> ArrayExpr
+# 183| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 183| StringLiteralExpr
-#-----| -> ErasureExpr
+# 183| [...]
+#-----| -> default separator
-# 183| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 183| [...]
+#-----| -> [...]
-# 185| IfStmt
-#-----| -> DeclRefExpr
+# 183| x is greater than 2
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 185| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 185| if ... then { ... } else { ... }
+#-----| -> <=
-# 185| BinaryExpr
-#-----| false -> [false] BinaryExpr
-#-----| true -> AutoClosureExpr
+# 185| x
+#-----| -> 2
-# 185| BinaryExpr
-#-----| false -> BinaryExpr
-#-----| true -> AutoClosureExpr
+# 185| ... call to <= ...
+#-----| false -> [false] ... call to && ...
+#-----| true -> { ... }
-# 185| [false] BinaryExpr
-#-----| false -> BinaryExpr
+# 185| ... call to && ...
+#-----| false -> ... call to && ...
+#-----| true -> { ... }
-# 185| BinaryExpr
+# 185| [false] ... call to && ...
+#-----| false -> ... call to && ...
+
+# 185| ... call to && ...
#-----| -> StmtCondition
# 185| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+#-----| true -> print
+#-----| false -> print
-# 185| DeclRefExpr
-#-----| -> TypeExpr
+# 185| <=
+#-----| -> Int.Type
-# 185| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 185| Int.Type
+#-----| -> call to <=
-# 185| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 185| call to <=
+#-----| exception -> exit m1 (normal)
+#-----| -> x
-# 185| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 185| 2
+#-----| -> ... call to <= ...
-# 185| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 185| x
+#-----| -> 0
-# 185| AutoClosureExpr
-#-----| -> DeclRefExpr
+# 185| ... call to > ...
+#-----| -> return ...
-# 185| BinaryExpr
-#-----| -> ReturnStmt
+# 185| return ...
+#-----| -> ... call to && ...
-# 185| ReturnStmt
-#-----| -> BinaryExpr
+# 185| { ... }
+#-----| -> >
-# 185| DeclRefExpr
-#-----| -> TypeExpr
+# 185| >
+#-----| -> Int.Type
-# 185| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 185| Int.Type
+#-----| -> call to >
-# 185| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 185| call to >
+#-----| exception -> exit m1 (normal)
+#-----| -> x
-# 185| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 185| 0
+#-----| -> ... call to > ...
-# 185| AutoClosureExpr
-#-----| -> DeclRefExpr
+# 185| call to ...
+#-----| -> return ...
-# 185| PrefixUnaryExpr
-#-----| -> ReturnStmt
+# 185| return ...
+#-----| -> ... call to && ...
-# 185| ReturnStmt
-#-----| -> BinaryExpr
+# 185| { ... }
+#-----| -> ==
-# 185| ParenExpr
-#-----| -> PrefixUnaryExpr
+# 185| (...)
+#-----| -> call to ...
-# 185| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 185| x
+#-----| -> 5
-# 185| BinaryExpr
-#-----| -> ParenExpr
+# 185| ... call to == ...
+#-----| -> (...)
-# 185| DeclRefExpr
-#-----| -> TypeExpr
+# 185| ==
+#-----| -> Int.Type
-# 185| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 185| Int.Type
+#-----| -> call to ==
-# 185| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 185| call to ==
+#-----| exception -> exit m1 (normal)
+#-----| -> x
-# 185| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 185| 5
+#-----| -> ... call to == ...
-# 186| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 186| print
+#-----| -> x is 1
-# 186| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 186| call to print
+#-----| exception -> exit m1 (normal)
-# 186| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 186| default separator
+#-----| -> default terminator
-# 186| DefaultArgumentExpr
-#-----| -> CallExpr
+# 186| default terminator
+#-----| -> call to print
-# 186| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 186| (Any) ...
+#-----| -> [...]
-# 186| ErasureExpr
-#-----| -> ArrayExpr
+# 186| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 186| StringLiteralExpr
-#-----| -> ErasureExpr
+# 186| [...]
+#-----| -> default separator
-# 186| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 186| [...]
+#-----| -> [...]
-# 189| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 186| x is 1
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 189| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 189| print
+#-----| -> I can't guess the number
-# 189| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 189| call to print
+#-----| exception -> exit m1 (normal)
-# 189| DefaultArgumentExpr
-#-----| -> CallExpr
+# 189| default separator
+#-----| -> default terminator
-# 189| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 189| default terminator
+#-----| -> call to print
-# 189| ErasureExpr
-#-----| -> ArrayExpr
+# 189| (Any) ...
+#-----| -> [...]
-# 189| StringLiteralExpr
-#-----| -> ErasureExpr
+# 189| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 189| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 189| I can't guess the number
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 193| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 189| [...]
+#-----| -> default separator
-# 193| exit ConcreteFuncDecl
+# 189| [...]
+#-----| -> [...]
-# 193| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 193| enter m2
+#-----| -> if ... then { ... }
-# 194| IfStmt
-#-----| -> DeclRefExpr
+# 193| exit m2
-# 194| DeclRefExpr
-#-----| -> StmtCondition
+# 193| exit m2 (normal)
+#-----| -> exit m2
+
+# 194| if ... then { ... }
+#-----| -> b
# 194| StmtCondition
-#-----| true -> IntegerLiteralExpr
-#-----| false -> IntegerLiteralExpr
+#-----| true -> 0
+#-----| false -> 1
-# 195| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 194| b
+#-----| -> StmtCondition
-# 195| IntegerLiteralExpr
-#-----| -> ReturnStmt
+# 195| return ...
+#-----| return -> exit m2 (normal)
-# 197| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 195| 0
+#-----| -> return ...
-# 197| IntegerLiteralExpr
-#-----| -> ReturnStmt
+# 197| return ...
+#-----| return -> exit m2 (normal)
-# 200| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 197| 1
+#-----| -> return ...
-# 200| exit ConcreteFuncDecl
+# 200| enter m3
+#-----| -> if ... then { ... }
-# 200| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 200| exit m3
-# 201| IfStmt
-#-----| -> DeclRefExpr
+# 200| exit m3 (normal)
+#-----| -> exit m3
-# 201| DeclRefExpr
-#-----| -> LoadExpr
+# 201| if ... then { ... }
+#-----| -> <
-# 201| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 201| (Int) ...
+#-----| -> 0
-# 201| BinaryExpr
+# 201| x
+#-----| -> (Int) ...
+
+# 201| ... call to < ...
#-----| -> StmtCondition
# 201| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+#-----| true -> x
+#-----| false -> x
-# 201| DeclRefExpr
-#-----| -> TypeExpr
+# 201| <
+#-----| -> Int.Type
-# 201| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 201| Int.Type
+#-----| -> call to <
-# 201| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 201| call to <
+#-----| exception -> exit m3 (normal)
+#-----| -> x
-# 201| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 201| 0
+#-----| -> ... call to < ...
-# 202| DeclRefExpr
-#-----| -> DeclRefExpr
+# 202| x
+#-----| -> -
-# 202| AssignExpr
-#-----| -> IfStmt
+# 202| ... = ...
+#-----| -> if ... then { ... }
-# 202| DeclRefExpr
-#-----| -> TypeExpr
+# 202| -
+#-----| -> Int.Type
-# 202| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 202| Int.Type
+#-----| -> call to -
-# 202| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 202| call to -
+#-----| exception -> exit m3 (normal)
+#-----| -> x
-# 202| PrefixUnaryExpr
-#-----| -> AssignExpr
+# 202| call to ...
+#-----| -> ... = ...
-# 202| DeclRefExpr
-#-----| -> LoadExpr
+# 202| (Int) ...
+#-----| -> call to ...
-# 202| LoadExpr
-#-----| -> PrefixUnaryExpr
+# 202| x
+#-----| -> (Int) ...
-# 203| IfStmt
-#-----| -> DeclRefExpr
+# 203| if ... then { ... }
+#-----| -> >
-# 203| DeclRefExpr
-#-----| -> LoadExpr
+# 203| (Int) ...
+#-----| -> 10
-# 203| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 203| x
+#-----| -> (Int) ...
-# 203| BinaryExpr
+# 203| ... call to > ...
#-----| -> StmtCondition
# 203| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+#-----| true -> x
+#-----| false -> x
-# 203| DeclRefExpr
-#-----| -> TypeExpr
+# 203| >
+#-----| -> Int.Type
-# 203| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 203| Int.Type
+#-----| -> call to >
-# 203| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 203| call to >
+#-----| exception -> exit m3 (normal)
+#-----| -> x
-# 203| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 203| 10
+#-----| -> ... call to > ...
-# 204| DeclRefExpr
-#-----| -> DeclRefExpr
+# 204| x
+#-----| -> -
-# 204| AssignExpr
-#-----| -> DeclRefExpr
+# 204| ... = ...
+#-----| -> x
-# 204| DeclRefExpr
-#-----| -> LoadExpr
+# 204| (Int) ...
+#-----| -> 1
-# 204| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 204| x
+#-----| -> (Int) ...
-# 204| BinaryExpr
-#-----| -> AssignExpr
+# 204| ... call to - ...
+#-----| -> ... = ...
-# 204| DeclRefExpr
-#-----| -> TypeExpr
+# 204| -
+#-----| -> Int.Type
-# 204| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 204| Int.Type
+#-----| -> call to -
-# 204| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 204| call to -
+#-----| exception -> exit m3 (normal)
+#-----| -> x
-# 204| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 204| 1
+#-----| -> ... call to - ...
-# 207| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 207| return ...
+#-----| return -> exit m3 (normal)
-# 207| DeclRefExpr
-#-----| -> LoadExpr
+# 207| (Int) ...
+#-----| -> return ...
-# 207| LoadExpr
-#-----| -> ReturnStmt
+# 207| x
+#-----| -> (Int) ...
-# 210| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 210| enter m4
+#-----| -> b1
-# 210| exit ConcreteFuncDecl
+# 210| exit m4
-# 210| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 210| exit m4 (normal)
+#-----| -> exit m4
-# 211| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 211| return ...
+#-----| return -> exit m4 (normal)
-# 211| [false] ParenExpr
-#-----| false -> StringLiteralExpr
+# 211| [false] (...)
+#-----| false -> !b2 || !b3
-# 211| [true] ParenExpr
-#-----| true -> StringLiteralExpr
+# 211| [true] (...)
+#-----| true -> b2 || b3
-# 211| IfExpr
-#-----| -> ReturnStmt
+# 211| ... ? ... : ...
+#-----| -> return ...
-# 211| DeclRefExpr
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+# 211| b1
+#-----| true -> b2
+#-----| false -> b3
-# 211| [false] IfExpr
-#-----| false -> [false] ParenExpr
+# 211| [false] ... ? ... : ...
+#-----| false -> [false] (...)
-# 211| [true] IfExpr
-#-----| true -> [true] ParenExpr
+# 211| [true] ... ? ... : ...
+#-----| true -> [true] (...)
-# 211| DeclRefExpr
-#-----| false -> [false] IfExpr
-#-----| true -> [true] IfExpr
+# 211| b2
+#-----| false -> [false] ... ? ... : ...
+#-----| true -> [true] ... ? ... : ...
-# 211| DeclRefExpr
-#-----| false -> [false] IfExpr
-#-----| true -> [true] IfExpr
+# 211| b3
+#-----| false -> [false] ... ? ... : ...
+#-----| true -> [true] ... ? ... : ...
-# 211| StringLiteralExpr
-#-----| -> IfExpr
+# 211| b2 || b3
+#-----| -> ... ? ... : ...
-# 211| StringLiteralExpr
-#-----| -> IfExpr
+# 211| !b2 || !b3
+#-----| -> ... ? ... : ...
-# 214| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 214| enter conversionsInSplitEntry
+#-----| -> if ... then { ... } else { ... }
-# 214| exit ConcreteFuncDecl
+# 214| exit conversionsInSplitEntry
-# 214| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 214| exit conversionsInSplitEntry (normal)
+#-----| -> exit conversionsInSplitEntry
-# 215| IfStmt
-#-----| -> DeclRefExpr
+# 215| if ... then { ... } else { ... }
+#-----| -> b
-# 215| DeclRefExpr
-#-----| true -> BooleanLiteralExpr
-#-----| false -> BooleanLiteralExpr
+# 215| b
+#-----| true -> true
+#-----| false -> false
-# 215| IfExpr
+# 215| ... ? ... : ...
#-----| -> StmtCondition
# 215| StmtCondition
-#-----| true -> StringLiteralExpr
-#-----| false -> StringLiteralExpr
+#-----| true -> b
+#-----| false -> !b
-# 215| ParenExpr
-#-----| -> IfExpr
+# 215| (...)
+#-----| -> ... ? ... : ...
-# 215| BooleanLiteralExpr
-#-----| -> ParenExpr
+# 215| true
+#-----| -> (...)
-# 215| CoerceExpr
-#-----| -> IfExpr
+# 215| (Bool) ...
+#-----| -> ... ? ... : ...
-# 215| BooleanLiteralExpr
-#-----| -> CoerceExpr
+# 215| false
+#-----| -> (Bool) ...
-# 216| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 216| return ...
+#-----| return -> exit conversionsInSplitEntry (normal)
-# 216| StringLiteralExpr
-#-----| -> ReturnStmt
+# 216| b
+#-----| -> return ...
-# 219| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 219| return ...
+#-----| return -> exit conversionsInSplitEntry (normal)
-# 219| StringLiteralExpr
-#-----| -> ReturnStmt
+# 219| !b
+#-----| -> return ...
-# 223| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 223| enter constant_condition
+#-----| -> if ... then { ... }
-# 223| exit ConcreteFuncDecl
+# 223| exit constant_condition
-# 223| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 223| exit constant_condition (normal)
+#-----| -> exit constant_condition
-# 224| IfStmt
-#-----| -> BooleanLiteralExpr
-
-# 224| PrefixUnaryExpr
-#-----| -> StmtCondition
+# 224| if ... then { ... }
+#-----| -> true
# 224| StmtCondition
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> DeclRefExpr
+#-----| false -> exit constant_condition (normal)
+#-----| true -> print
-# 224| BooleanLiteralExpr
-#-----| -> PrefixUnaryExpr
-
-# 225| DeclRefExpr
-#-----| -> StringLiteralExpr
-
-# 225| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-
-# 225| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
-
-# 225| DefaultArgumentExpr
-#-----| -> CallExpr
-
-# 225| ArrayExpr
-#-----| -> VarargExpansionExpr
-
-# 225| ErasureExpr
-#-----| -> ArrayExpr
-
-# 225| StringLiteralExpr
-#-----| -> ErasureExpr
-
-# 225| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
-
-# 229| enter ConcreteFuncDecl
-#-----| -> IfStmt
-
-# 229| exit ConcreteFuncDecl
-
-# 229| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
-
-# 230| IfStmt
-#-----| -> DeclRefExpr
-
-# 230| DeclRefExpr
+# 224| call to ...
#-----| -> StmtCondition
+# 224| true
+#-----| -> call to ...
+
+# 225| print
+#-----| -> Impossible
+
+# 225| call to print
+#-----| exception -> exit constant_condition (normal)
+
+# 225| default separator
+#-----| -> default terminator
+
+# 225| default terminator
+#-----| -> call to print
+
+# 225| (Any) ...
+#-----| -> [...]
+
+# 225| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
+
+# 225| Impossible
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
+
+# 225| [...]
+#-----| -> default separator
+
+# 225| [...]
+#-----| -> [...]
+
+# 229| enter empty_else
+#-----| -> if ... then { ... } else { ... }
+
+# 229| exit empty_else
+
+# 229| exit empty_else (normal)
+#-----| -> exit empty_else
+
+# 230| if ... then { ... } else { ... }
+#-----| -> b
+
# 230| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> BraceStmt
+#-----| true -> print
+#-----| false -> { ... }
-# 231| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 230| b
+#-----| -> StmtCondition
-# 231| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 231| print
+#-----| -> true
-# 231| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 231| call to print
+#-----| exception -> exit empty_else (normal)
+#-----| -> print
-# 231| DefaultArgumentExpr
-#-----| -> CallExpr
+# 231| default separator
+#-----| -> default terminator
-# 231| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 231| default terminator
+#-----| -> call to print
-# 231| ErasureExpr
-#-----| -> ArrayExpr
+# 231| (Any) ...
+#-----| -> [...]
-# 231| StringLiteralExpr
-#-----| -> ErasureExpr
+# 231| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 231| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 231| [...]
+#-----| -> default separator
-# 233| BraceStmt
-#-----| -> DeclRefExpr
+# 231| [...]
+#-----| -> [...]
-# 234| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 231| true
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 234| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 233| { ... }
+#-----| -> print
-# 234| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 234| print
+#-----| -> done
-# 234| DefaultArgumentExpr
-#-----| -> CallExpr
+# 234| call to print
+#-----| exception -> exit empty_else (normal)
-# 234| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 234| default separator
+#-----| -> default terminator
-# 234| ErasureExpr
-#-----| -> ArrayExpr
+# 234| default terminator
+#-----| -> call to print
-# 234| StringLiteralExpr
-#-----| -> ErasureExpr
+# 234| (Any) ...
+#-----| -> [...]
-# 234| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 234| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 237| enter ConcreteFuncDecl
-#-----| -> IfStmt
+# 234| [...]
+#-----| -> default separator
-# 237| exit ConcreteFuncDecl
+# 234| [...]
+#-----| -> [...]
-# 237| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 234| done
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 238| IfStmt
-#-----| -> DeclRefExpr
+# 237| enter disjunct
+#-----| -> if ... then { ... }
-# 238| ParenExpr
+# 237| exit disjunct
+
+# 237| exit disjunct (normal)
+#-----| -> exit disjunct
+
+# 238| if ... then { ... }
+#-----| -> b1
+
+# 238| (...)
#-----| -> StmtCondition
# 238| StmtCondition
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> DeclRefExpr
+#-----| false -> exit disjunct (normal)
+#-----| true -> print
-# 238| DeclRefExpr
-#-----| true -> BinaryExpr
-#-----| false -> AutoClosureExpr
+# 238| b1
+#-----| true -> ... call to || ...
+#-----| false -> { ... }
-# 238| BinaryExpr
-#-----| -> ParenExpr
+# 238| ... call to || ...
+#-----| -> (...)
-# 238| AutoClosureExpr
-#-----| -> DeclRefExpr
+# 238| b2
+#-----| -> return ...
-# 238| DeclRefExpr
-#-----| -> ReturnStmt
+# 238| return ...
+#-----| -> ... call to || ...
-# 238| ReturnStmt
-#-----| -> BinaryExpr
+# 238| { ... }
+#-----| -> b2
-# 239| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 239| print
+#-----| -> b1 or b2
-# 239| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 239| call to print
+#-----| exception -> exit disjunct (normal)
-# 239| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 239| default separator
+#-----| -> default terminator
-# 239| DefaultArgumentExpr
-#-----| -> CallExpr
+# 239| default terminator
+#-----| -> call to print
-# 239| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 239| (Any) ...
+#-----| -> [...]
-# 239| ErasureExpr
-#-----| -> ArrayExpr
+# 239| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 239| StringLiteralExpr
-#-----| -> ErasureExpr
+# 239| [...]
+#-----| -> default separator
-# 239| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 239| [...]
+#-----| -> [...]
-# 243| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 239| b1 or b2
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 243| exit ConcreteFuncDecl
+# 243| enter binaryExprs
+#-----| -> c
-# 243| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 243| exit binaryExprs
-# 244| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 243| exit binaryExprs (normal)
+#-----| -> exit binaryExprs
-# 244| ConcreteVarDecl
-#-----| -> NamedPattern
+# 244| var ... = ...
+#-----| -> c
-# 244| NamedPattern
-#-----| -> DeclRefExpr
+# 244| c
+#-----| -> +
-# 244| DeclRefExpr
-#-----| -> DeclRefExpr
+# 244| c
+#-----| -> d
-# 244| BinaryExpr
-#-----| -> PatternBindingDecl
+# 244| a
+#-----| -> b
-# 244| DeclRefExpr
-#-----| -> TypeExpr
+# 244| ... call to + ...
+#-----| -> var ... = ...
-# 244| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 244| +
+#-----| -> Int.Type
-# 244| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 244| Int.Type
+#-----| -> call to +
-# 244| DeclRefExpr
-#-----| -> BinaryExpr
+# 244| call to +
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 245| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 244| b
+#-----| -> ... call to + ...
-# 245| ConcreteVarDecl
-#-----| -> NamedPattern
+# 245| var ... = ...
+#-----| -> d
-# 245| NamedPattern
-#-----| -> DeclRefExpr
+# 245| d
+#-----| -> -
-# 245| DeclRefExpr
-#-----| -> DeclRefExpr
+# 245| d
+#-----| -> e
-# 245| BinaryExpr
-#-----| -> PatternBindingDecl
+# 245| a
+#-----| -> b
-# 245| DeclRefExpr
-#-----| -> TypeExpr
+# 245| ... call to - ...
+#-----| -> var ... = ...
-# 245| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 245| -
+#-----| -> Int.Type
-# 245| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 245| Int.Type
+#-----| -> call to -
-# 245| DeclRefExpr
-#-----| -> BinaryExpr
+# 245| call to -
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 246| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 245| b
+#-----| -> ... call to - ...
-# 246| ConcreteVarDecl
-#-----| -> NamedPattern
+# 246| var ... = ...
+#-----| -> e
-# 246| NamedPattern
-#-----| -> DeclRefExpr
+# 246| e
+#-----| -> *
-# 246| DeclRefExpr
-#-----| -> DeclRefExpr
+# 246| e
+#-----| -> f
-# 246| BinaryExpr
-#-----| -> PatternBindingDecl
+# 246| a
+#-----| -> b
-# 246| DeclRefExpr
-#-----| -> TypeExpr
+# 246| ... call to * ...
+#-----| -> var ... = ...
-# 246| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 246| *
+#-----| -> Int.Type
-# 246| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 246| Int.Type
+#-----| -> call to *
-# 246| DeclRefExpr
-#-----| -> BinaryExpr
+# 246| call to *
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 247| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 246| b
+#-----| -> ... call to * ...
-# 247| ConcreteVarDecl
-#-----| -> NamedPattern
+# 247| var ... = ...
+#-----| -> f
-# 247| NamedPattern
-#-----| -> DeclRefExpr
+# 247| f
+#-----| -> /
-# 247| DeclRefExpr
-#-----| -> DeclRefExpr
+# 247| f
+#-----| -> g
-# 247| BinaryExpr
-#-----| -> PatternBindingDecl
+# 247| a
+#-----| -> b
-# 247| DeclRefExpr
-#-----| -> TypeExpr
+# 247| ... call to / ...
+#-----| -> var ... = ...
-# 247| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 247| /
+#-----| -> Int.Type
-# 247| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 247| Int.Type
+#-----| -> call to /
-# 247| DeclRefExpr
-#-----| -> BinaryExpr
+# 247| call to /
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 248| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 247| b
+#-----| -> ... call to / ...
-# 248| ConcreteVarDecl
-#-----| -> NamedPattern
+# 248| var ... = ...
+#-----| -> g
-# 248| NamedPattern
-#-----| -> DeclRefExpr
+# 248| g
+#-----| -> %
-# 248| DeclRefExpr
-#-----| -> DeclRefExpr
+# 248| g
+#-----| -> h
-# 248| BinaryExpr
-#-----| -> PatternBindingDecl
+# 248| a
+#-----| -> b
-# 248| DeclRefExpr
-#-----| -> TypeExpr
+# 248| ... call to % ...
+#-----| -> var ... = ...
-# 248| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 248| %
+#-----| -> Int.Type
-# 248| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 248| Int.Type
+#-----| -> call to %
-# 248| DeclRefExpr
-#-----| -> BinaryExpr
+# 248| call to %
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 249| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 248| b
+#-----| -> ... call to % ...
-# 249| ConcreteVarDecl
-#-----| -> NamedPattern
+# 249| var ... = ...
+#-----| -> h
-# 249| NamedPattern
-#-----| -> DeclRefExpr
+# 249| h
+#-----| -> &
-# 249| DeclRefExpr
-#-----| -> DeclRefExpr
+# 249| h
+#-----| -> i
-# 249| BinaryExpr
-#-----| -> PatternBindingDecl
+# 249| a
+#-----| -> b
-# 249| DeclRefExpr
-#-----| -> TypeExpr
+# 249| ... call to & ...
+#-----| -> var ... = ...
-# 249| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 249| &
+#-----| -> Int.Type
-# 249| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 249| Int.Type
+#-----| -> call to &
-# 249| DeclRefExpr
-#-----| -> BinaryExpr
+# 249| call to &
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 250| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 249| b
+#-----| -> ... call to & ...
-# 250| ConcreteVarDecl
-#-----| -> NamedPattern
+# 250| var ... = ...
+#-----| -> i
-# 250| NamedPattern
-#-----| -> DeclRefExpr
+# 250| i
+#-----| -> |
-# 250| DeclRefExpr
-#-----| -> DeclRefExpr
+# 250| i
+#-----| -> j
-# 250| BinaryExpr
-#-----| -> PatternBindingDecl
+# 250| a
+#-----| -> b
-# 250| DeclRefExpr
-#-----| -> TypeExpr
+# 250| ... call to | ...
+#-----| -> var ... = ...
-# 250| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 250| Int.Type
+#-----| -> call to |
-# 250| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 250| call to |
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 250| DeclRefExpr
-#-----| -> BinaryExpr
+# 250| |
+#-----| -> Int.Type
-# 251| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 250| b
+#-----| -> ... call to | ...
-# 251| ConcreteVarDecl
-#-----| -> NamedPattern
+# 251| var ... = ...
+#-----| -> j
-# 251| NamedPattern
-#-----| -> DeclRefExpr
+# 251| j
+#-----| -> ^
-# 251| DeclRefExpr
-#-----| -> DeclRefExpr
+# 251| j
+#-----| -> k
-# 251| BinaryExpr
-#-----| -> PatternBindingDecl
+# 251| a
+#-----| -> b
-# 251| DeclRefExpr
-#-----| -> TypeExpr
+# 251| ... call to ^ ...
+#-----| -> var ... = ...
-# 251| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 251| Int.Type
+#-----| -> call to ^
-# 251| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 251| ^
+#-----| -> Int.Type
-# 251| DeclRefExpr
-#-----| -> BinaryExpr
+# 251| call to ^
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 252| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 251| b
+#-----| -> ... call to ^ ...
-# 252| ConcreteVarDecl
-#-----| -> NamedPattern
+# 252| var ... = ...
+#-----| -> k
-# 252| NamedPattern
-#-----| -> DeclRefExpr
+# 252| k
+#-----| -> <<
-# 252| DeclRefExpr
-#-----| -> DeclRefExpr
+# 252| k
+#-----| -> l
-# 252| BinaryExpr
-#-----| -> PatternBindingDecl
+# 252| a
+#-----| -> b
-# 252| DeclRefExpr
-#-----| -> TypeExpr
+# 252| ... call to << ...
+#-----| -> var ... = ...
-# 252| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 252| <<
+#-----| -> Int.Type
-# 252| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 252| Int.Type
+#-----| -> call to <<
-# 252| DeclRefExpr
-#-----| -> BinaryExpr
+# 252| call to <<
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 253| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 252| b
+#-----| -> ... call to << ...
-# 253| ConcreteVarDecl
-#-----| -> NamedPattern
+# 253| var ... = ...
+#-----| -> l
-# 253| NamedPattern
-#-----| -> DeclRefExpr
+# 253| l
+#-----| -> >>
-# 253| DeclRefExpr
-#-----| -> DeclRefExpr
+# 253| l
+#-----| -> o
-# 253| BinaryExpr
-#-----| -> PatternBindingDecl
+# 253| a
+#-----| -> b
-# 253| DeclRefExpr
-#-----| -> TypeExpr
+# 253| ... call to >> ...
+#-----| -> var ... = ...
-# 253| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 253| >>
+#-----| -> Int.Type
-# 253| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 253| Int.Type
+#-----| -> call to >>
-# 253| DeclRefExpr
-#-----| -> BinaryExpr
+# 253| call to >>
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 254| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 253| b
+#-----| -> ... call to >> ...
-# 254| ConcreteVarDecl
-#-----| -> NamedPattern
+# 254| var ... = ...
+#-----| -> o
-# 254| NamedPattern
-#-----| -> DeclRefExpr
+# 254| o
+#-----| -> ==
-# 254| DeclRefExpr
-#-----| -> DeclRefExpr
+# 254| o
+#-----| -> p
-# 254| BinaryExpr
-#-----| -> PatternBindingDecl
+# 254| a
+#-----| -> b
-# 254| DeclRefExpr
-#-----| -> TypeExpr
+# 254| ... call to == ...
+#-----| -> var ... = ...
-# 254| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 254| ==
+#-----| -> Int.Type
-# 254| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 254| Int.Type
+#-----| -> call to ==
-# 254| DeclRefExpr
-#-----| -> BinaryExpr
+# 254| call to ==
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 255| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 254| b
+#-----| -> ... call to == ...
-# 255| ConcreteVarDecl
-#-----| -> NamedPattern
+# 255| var ... = ...
+#-----| -> p
-# 255| NamedPattern
-#-----| -> DeclRefExpr
+# 255| p
+#-----| -> !=
-# 255| DeclRefExpr
-#-----| -> DeclRefExpr
+# 255| p
+#-----| -> q
-# 255| BinaryExpr
-#-----| -> PatternBindingDecl
+# 255| a
+#-----| -> b
-# 255| DeclRefExpr
-#-----| -> TypeExpr
+# 255| ... call to != ...
+#-----| -> var ... = ...
-# 255| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 255| !=
+#-----| -> Int.Type
-# 255| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 255| Int.Type
+#-----| -> call to !=
-# 255| DeclRefExpr
-#-----| -> BinaryExpr
+# 255| call to !=
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 256| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 255| b
+#-----| -> ... call to != ...
-# 256| ConcreteVarDecl
-#-----| -> NamedPattern
+# 256| var ... = ...
+#-----| -> q
-# 256| NamedPattern
-#-----| -> DeclRefExpr
+# 256| q
+#-----| -> <
-# 256| DeclRefExpr
-#-----| -> DeclRefExpr
+# 256| q
+#-----| -> r
-# 256| BinaryExpr
-#-----| -> PatternBindingDecl
+# 256| a
+#-----| -> b
-# 256| DeclRefExpr
-#-----| -> TypeExpr
+# 256| ... call to < ...
+#-----| -> var ... = ...
-# 256| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 256| <
+#-----| -> Int.Type
-# 256| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 256| Int.Type
+#-----| -> call to <
-# 256| DeclRefExpr
-#-----| -> BinaryExpr
+# 256| call to <
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 257| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 256| b
+#-----| -> ... call to < ...
-# 257| ConcreteVarDecl
-#-----| -> NamedPattern
+# 257| var ... = ...
+#-----| -> r
-# 257| NamedPattern
-#-----| -> DeclRefExpr
+# 257| r
+#-----| -> <=
-# 257| DeclRefExpr
-#-----| -> DeclRefExpr
+# 257| r
+#-----| -> s
-# 257| BinaryExpr
-#-----| -> PatternBindingDecl
+# 257| a
+#-----| -> b
-# 257| DeclRefExpr
-#-----| -> TypeExpr
+# 257| ... call to <= ...
+#-----| -> var ... = ...
-# 257| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 257| <=
+#-----| -> Int.Type
-# 257| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 257| Int.Type
+#-----| -> call to <=
-# 257| DeclRefExpr
-#-----| -> BinaryExpr
+# 257| call to <=
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 258| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 257| b
+#-----| -> ... call to <= ...
-# 258| ConcreteVarDecl
-#-----| -> NamedPattern
+# 258| var ... = ...
+#-----| -> s
-# 258| NamedPattern
-#-----| -> DeclRefExpr
+# 258| s
+#-----| -> >
-# 258| DeclRefExpr
-#-----| -> DeclRefExpr
+# 258| s
+#-----| -> t
-# 258| BinaryExpr
-#-----| -> PatternBindingDecl
+# 258| a
+#-----| -> b
-# 258| DeclRefExpr
-#-----| -> TypeExpr
+# 258| ... call to > ...
+#-----| -> var ... = ...
-# 258| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 258| >
+#-----| -> Int.Type
-# 258| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 258| Int.Type
+#-----| -> call to >
-# 258| DeclRefExpr
-#-----| -> BinaryExpr
+# 258| call to >
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 259| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 258| b
+#-----| -> ... call to > ...
-# 259| ConcreteVarDecl
-#-----| -> exit ConcreteFuncDecl (normal)
+# 259| var ... = ...
+#-----| -> t
-# 259| NamedPattern
-#-----| -> DeclRefExpr
+# 259| t
+#-----| -> >=
-# 259| DeclRefExpr
-#-----| -> DeclRefExpr
+# 259| t
+#-----| -> exit binaryExprs (normal)
-# 259| BinaryExpr
-#-----| -> PatternBindingDecl
+# 259| a
+#-----| -> b
-# 259| DeclRefExpr
-#-----| -> TypeExpr
+# 259| ... call to >= ...
+#-----| -> var ... = ...
-# 259| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 259| >=
+#-----| -> Int.Type
-# 259| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 259| Int.Type
+#-----| -> call to >=
-# 259| DeclRefExpr
-#-----| -> BinaryExpr
+# 259| call to >=
+#-----| exception -> exit binaryExprs (normal)
+#-----| -> a
-# 262| enter ConcreteFuncDecl
-#-----| -> InterpolatedStringLiteralExpr
+# 259| b
+#-----| -> ... call to >= ...
-# 262| exit ConcreteFuncDecl
+# 262| enter interpolatedString
+#-----| -> "..."
-# 262| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 262| exit interpolatedString
-# 263| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 262| exit interpolatedString (normal)
+#-----| -> exit interpolatedString
-# 263| InterpolatedStringLiteralExpr
-#-----| -> ReturnStmt
+# 263| return ...
+#-----| return -> exit interpolatedString (normal)
-# 266| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 263| "..."
+#-----| -> return ...
-# 266| exit ConcreteFuncDecl
+# 266| enter testSubscriptExpr
+#-----| -> a
-# 266| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 266| exit testSubscriptExpr
-# 267| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 266| exit testSubscriptExpr (normal)
+#-----| -> exit testSubscriptExpr
-# 267| ConcreteVarDecl
-#-----| -> DeclRefExpr
+# 267| var ... = ...
+#-----| -> a
-# 267| NamedPattern
-#-----| -> IntegerLiteralExpr
+# 267| a
+#-----| -> 0
-# 267| ArrayExpr
-#-----| -> PatternBindingDecl
+# 267| a
+#-----| -> a
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| [...]
+#-----| -> var ... = ...
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 0
+#-----| -> 1
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 1
+#-----| -> 2
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 2
+#-----| -> 3
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 3
+#-----| -> 4
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 4
+#-----| -> 5
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 5
+#-----| -> 6
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 6
+#-----| -> 7
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 7
+#-----| -> 8
-# 267| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 267| 8
+#-----| -> 9
-# 267| IntegerLiteralExpr
-#-----| -> ArrayExpr
+# 267| 9
+#-----| -> 10
-# 268| DeclRefExpr
-#-----| -> InOutExpr
+# 267| 10
+#-----| -> [...]
-# 268| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 268| &...
+#-----| -> 0
-# 268| SubscriptExpr
-#-----| -> IntegerLiteralExpr
+# 268| a
+#-----| -> &...
-# 268| AssignExpr
-#-----| -> DeclRefExpr
+# 268| ...[...]
+#-----| -> 0
-# 268| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 268| setter for ... = ...
+#-----| -> +=
-# 268| IntegerLiteralExpr
-#-----| -> AssignExpr
+# 268| 0
+#-----| -> ...[...]
-# 269| DeclRefExpr
-#-----| -> InOutExpr
+# 268| 0
+#-----| -> setter for ... = ...
-# 269| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 269| &...
+#-----| -> 1
-# 269| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 269| a
+#-----| -> &...
-# 269| SubscriptExpr
-#-----| -> InOutExpr
+# 269| &...
+#-----| -> 1
-# 269| BinaryExpr
-#-----| -> DeclRefExpr
+# 269| getter for ...[...]
+#-----| -> &...
-# 269| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 269| ... call to += ...
+#-----| -> -=
-# 269| DeclRefExpr
-#-----| -> TypeExpr
+# 269| 1
+#-----| -> getter for ...[...]
-# 269| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 269| +=
+#-----| -> Int.Type
-# 269| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 269| Int.Type
+#-----| -> call to +=
-# 269| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 269| call to +=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 270| DeclRefExpr
-#-----| -> InOutExpr
+# 269| 1
+#-----| -> ... call to += ...
-# 270| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 270| &...
+#-----| -> 2
-# 270| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 270| a
+#-----| -> &...
-# 270| SubscriptExpr
-#-----| -> InOutExpr
+# 270| &...
+#-----| -> 1
-# 270| BinaryExpr
-#-----| -> DeclRefExpr
+# 270| getter for ...[...]
+#-----| -> &...
-# 270| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 270| ... call to -= ...
+#-----| -> *=
-# 270| DeclRefExpr
-#-----| -> TypeExpr
+# 270| 2
+#-----| -> getter for ...[...]
-# 270| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 270| -=
+#-----| -> Int.Type
-# 270| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 270| Int.Type
+#-----| -> call to -=
-# 270| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 270| call to -=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 271| DeclRefExpr
-#-----| -> InOutExpr
+# 270| 1
+#-----| -> ... call to -= ...
-# 271| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 271| &...
+#-----| -> 3
-# 271| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 271| a
+#-----| -> &...
-# 271| SubscriptExpr
-#-----| -> InOutExpr
+# 271| &...
+#-----| -> 1
-# 271| BinaryExpr
-#-----| -> DeclRefExpr
+# 271| getter for ...[...]
+#-----| -> &...
-# 271| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 271| ... call to *= ...
+#-----| -> /=
-# 271| DeclRefExpr
-#-----| -> TypeExpr
+# 271| 3
+#-----| -> getter for ...[...]
-# 271| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 271| *=
+#-----| -> Int.Type
-# 271| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 271| Int.Type
+#-----| -> call to *=
-# 271| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 271| call to *=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 272| DeclRefExpr
-#-----| -> InOutExpr
+# 271| 1
+#-----| -> ... call to *= ...
-# 272| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 272| &...
+#-----| -> 4
-# 272| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 272| a
+#-----| -> &...
-# 272| SubscriptExpr
-#-----| -> InOutExpr
+# 272| &...
+#-----| -> 1
-# 272| BinaryExpr
-#-----| -> DeclRefExpr
+# 272| getter for ...[...]
+#-----| -> &...
-# 272| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 272| ... call to /= ...
+#-----| -> %=
-# 272| DeclRefExpr
-#-----| -> TypeExpr
+# 272| 4
+#-----| -> getter for ...[...]
-# 272| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 272| /=
+#-----| -> Int.Type
-# 272| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 272| Int.Type
+#-----| -> call to /=
-# 272| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 272| call to /=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 273| DeclRefExpr
-#-----| -> InOutExpr
+# 272| 1
+#-----| -> ... call to /= ...
-# 273| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 273| &...
+#-----| -> 5
-# 273| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 273| a
+#-----| -> &...
-# 273| SubscriptExpr
-#-----| -> InOutExpr
+# 273| &...
+#-----| -> 1
-# 273| BinaryExpr
-#-----| -> DeclRefExpr
+# 273| getter for ...[...]
+#-----| -> &...
-# 273| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 273| ... call to %= ...
+#-----| -> &=
-# 273| DeclRefExpr
-#-----| -> TypeExpr
+# 273| 5
+#-----| -> getter for ...[...]
-# 273| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 273| %=
+#-----| -> Int.Type
-# 273| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 273| Int.Type
+#-----| -> call to %=
-# 273| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 273| call to %=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 274| DeclRefExpr
-#-----| -> InOutExpr
+# 273| 1
+#-----| -> ... call to %= ...
-# 274| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 274| &...
+#-----| -> 6
-# 274| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 274| a
+#-----| -> &...
-# 274| SubscriptExpr
-#-----| -> InOutExpr
+# 274| &...
+#-----| -> 1
-# 274| BinaryExpr
-#-----| -> DeclRefExpr
+# 274| getter for ...[...]
+#-----| -> &...
-# 274| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 274| ... call to &= ...
+#-----| -> |=
-# 274| DeclRefExpr
-#-----| -> TypeExpr
+# 274| 6
+#-----| -> getter for ...[...]
-# 274| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 274| &=
+#-----| -> Int.Type
-# 274| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 274| Int.Type
+#-----| -> call to &=
-# 274| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 274| call to &=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 275| DeclRefExpr
-#-----| -> InOutExpr
+# 274| 1
+#-----| -> ... call to &= ...
-# 275| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 275| &...
+#-----| -> 7
-# 275| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 275| a
+#-----| -> &...
-# 275| SubscriptExpr
-#-----| -> InOutExpr
+# 275| &...
+#-----| -> 1
-# 275| BinaryExpr
-#-----| -> DeclRefExpr
+# 275| getter for ...[...]
+#-----| -> &...
-# 275| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 275| ... call to |= ...
+#-----| -> ^=
-# 275| DeclRefExpr
-#-----| -> TypeExpr
+# 275| 7
+#-----| -> getter for ...[...]
-# 275| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 275| Int.Type
+#-----| -> call to |=
-# 275| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 275| call to |=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 275| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 275| |=
+#-----| -> Int.Type
-# 276| DeclRefExpr
-#-----| -> InOutExpr
+# 275| 1
+#-----| -> ... call to |= ...
-# 276| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 276| &...
+#-----| -> 8
-# 276| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 276| a
+#-----| -> &...
-# 276| SubscriptExpr
-#-----| -> InOutExpr
+# 276| &...
+#-----| -> 1
-# 276| BinaryExpr
-#-----| -> DeclRefExpr
+# 276| getter for ...[...]
+#-----| -> &...
-# 276| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 276| ... call to ^= ...
+#-----| -> <<=
-# 276| DeclRefExpr
-#-----| -> TypeExpr
+# 276| 8
+#-----| -> getter for ...[...]
-# 276| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 276| Int.Type
+#-----| -> call to ^=
-# 276| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 276| ^=
+#-----| -> Int.Type
-# 276| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 276| call to ^=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 277| DeclRefExpr
-#-----| -> InOutExpr
+# 276| 1
+#-----| -> ... call to ^= ...
-# 277| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 277| &...
+#-----| -> 9
-# 277| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 277| a
+#-----| -> &...
-# 277| SubscriptExpr
-#-----| -> InOutExpr
+# 277| &...
+#-----| -> 1
-# 277| BinaryExpr
-#-----| -> DeclRefExpr
+# 277| getter for ...[...]
+#-----| -> &...
-# 277| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 277| ... call to <<= ...
+#-----| -> >>=
-# 277| DeclRefExpr
-#-----| -> TypeExpr
+# 277| 9
+#-----| -> getter for ...[...]
-# 277| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 277| <<=
+#-----| -> Int.Type
-# 277| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 277| Int.Type
+#-----| -> call to <<=
-# 277| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 277| call to <<=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 278| DeclRefExpr
-#-----| -> InOutExpr
+# 277| 1
+#-----| -> ... call to <<= ...
-# 278| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 278| &...
+#-----| -> 10
-# 278| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 278| a
+#-----| -> &...
-# 278| SubscriptExpr
-#-----| -> InOutExpr
+# 278| &...
+#-----| -> 1
-# 278| BinaryExpr
-#-----| -> NamedPattern
+# 278| getter for ...[...]
+#-----| -> &...
-# 278| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 278| ... call to >>= ...
+#-----| -> tupleWithA
-# 278| DeclRefExpr
-#-----| -> TypeExpr
+# 278| 10
+#-----| -> getter for ...[...]
-# 278| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 278| >>=
+#-----| -> Int.Type
-# 278| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 278| Int.Type
+#-----| -> call to >>=
-# 278| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 278| call to >>=
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a
-# 280| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 278| 1
+#-----| -> ... call to >>= ...
-# 280| ConcreteVarDecl
-#-----| -> NamedPattern
+# 280| var ... = ...
+#-----| -> tupleWithA
-# 280| NamedPattern
-#-----| -> DeclRefExpr
+# 280| tupleWithA
+#-----| -> a
-# 280| TupleExpr
-#-----| -> PatternBindingDecl
+# 280| tupleWithA
+#-----| -> b
-# 280| DeclRefExpr
-#-----| -> InOutExpr
+# 280| (...)
+#-----| -> var ... = ...
-# 280| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 280| &...
+#-----| -> 0
-# 280| LoadExpr
-#-----| -> DeclRefExpr
+# 280| a
+#-----| -> &...
-# 280| SubscriptExpr
-#-----| -> LoadExpr
+# 280| (Int) ...
+#-----| -> a
-# 280| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 280| getter for ...[...]
+#-----| -> (Int) ...
-# 280| DeclRefExpr
-#-----| -> InOutExpr
+# 280| 0
+#-----| -> getter for ...[...]
-# 280| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 280| &...
+#-----| -> 1
-# 280| LoadExpr
-#-----| -> DeclRefExpr
+# 280| a
+#-----| -> &...
-# 280| SubscriptExpr
-#-----| -> LoadExpr
+# 280| (Int) ...
+#-----| -> a
-# 280| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 280| getter for ...[...]
+#-----| -> (Int) ...
-# 280| DeclRefExpr
-#-----| -> InOutExpr
+# 280| 1
+#-----| -> getter for ...[...]
-# 280| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 280| &...
+#-----| -> 2
-# 280| LoadExpr
-#-----| -> DeclRefExpr
+# 280| a
+#-----| -> &...
-# 280| SubscriptExpr
-#-----| -> LoadExpr
+# 280| (Int) ...
+#-----| -> a
-# 280| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 280| getter for ...[...]
+#-----| -> (Int) ...
-# 280| DeclRefExpr
-#-----| -> InOutExpr
+# 280| 2
+#-----| -> getter for ...[...]
-# 280| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 280| &...
+#-----| -> 3
-# 280| LoadExpr
-#-----| -> DeclRefExpr
+# 280| a
+#-----| -> &...
-# 280| SubscriptExpr
-#-----| -> LoadExpr
+# 280| (Int) ...
+#-----| -> a
-# 280| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 280| getter for ...[...]
+#-----| -> (Int) ...
-# 280| DeclRefExpr
-#-----| -> InOutExpr
+# 280| 3
+#-----| -> getter for ...[...]
-# 280| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 280| &...
+#-----| -> 4
-# 280| LoadExpr
-#-----| -> TupleExpr
+# 280| a
+#-----| -> &...
-# 280| SubscriptExpr
-#-----| -> LoadExpr
+# 280| (Int) ...
+#-----| -> (...)
-# 280| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 280| getter for ...[...]
+#-----| -> (Int) ...
-# 282| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 280| 4
+#-----| -> getter for ...[...]
-# 282| ConcreteVarDecl
-#-----| -> DeclRefExpr
+# 282| var ... = ...
+#-----| -> b
-# 282| NamedPattern
-#-----| -> IntegerLiteralExpr
+# 282| b
+#-----| -> 0
-# 282| ArrayExpr
-#-----| -> PatternBindingDecl
+# 282| b
+#-----| -> b
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| [...]
+#-----| -> var ... = ...
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 0
+#-----| -> 1
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 1
+#-----| -> 2
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 2
+#-----| -> 3
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 3
+#-----| -> 4
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 4
+#-----| -> 5
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 5
+#-----| -> 6
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 6
+#-----| -> 7
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 7
+#-----| -> 8
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 8
+#-----| -> 9
-# 282| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 282| 9
+#-----| -> 10
-# 282| IntegerLiteralExpr
-#-----| -> ArrayExpr
+# 282| 10
+#-----| -> 11
-# 283| DeclRefExpr
-#-----| -> InOutExpr
+# 282| 11
+#-----| -> [...]
-# 283| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 283| &...
+#-----| -> 0
-# 283| SubscriptExpr
-#-----| -> DeclRefExpr
+# 283| b
+#-----| -> &...
-# 283| AssignExpr
-#-----| -> DeclRefExpr
+# 283| ...[...]
+#-----| -> a
-# 283| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 283| setter for ... = ...
+#-----| -> b
-# 283| DeclRefExpr
-#-----| -> InOutExpr
+# 283| 0
+#-----| -> ...[...]
-# 283| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 283| &...
+#-----| -> 10
-# 283| LoadExpr
-#-----| -> AssignExpr
+# 283| a
+#-----| -> &...
-# 283| SubscriptExpr
-#-----| -> LoadExpr
+# 283| (Int) ...
+#-----| -> setter for ... = ...
-# 283| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 283| getter for ...[...]
+#-----| -> (Int) ...
-# 284| DeclRefExpr
-#-----| -> InOutExpr
+# 283| 10
+#-----| -> getter for ...[...]
-# 284| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 284| &...
+#-----| -> 1
-# 284| SubscriptExpr
-#-----| -> DeclRefExpr
+# 284| b
+#-----| -> &...
-# 284| AssignExpr
-#-----| -> DeclRefExpr
+# 284| ...[...]
+#-----| -> +
-# 284| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 284| setter for ... = ...
+#-----| -> b
-# 284| DeclRefExpr
-#-----| -> InOutExpr
+# 284| 1
+#-----| -> ...[...]
-# 284| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 284| &...
+#-----| -> 0
-# 284| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 284| b
+#-----| -> &...
-# 284| SubscriptExpr
-#-----| -> LoadExpr
+# 284| (Int) ...
+#-----| -> 1
-# 284| BinaryExpr
-#-----| -> AssignExpr
+# 284| getter for ...[...]
+#-----| -> (Int) ...
-# 284| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 284| ... call to + ...
+#-----| -> setter for ... = ...
-# 284| DeclRefExpr
-#-----| -> TypeExpr
+# 284| 0
+#-----| -> getter for ...[...]
-# 284| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 284| +
+#-----| -> Int.Type
-# 284| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 284| Int.Type
+#-----| -> call to +
-# 284| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 284| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 285| DeclRefExpr
-#-----| -> InOutExpr
+# 284| 1
+#-----| -> ... call to + ...
-# 285| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 285| &...
+#-----| -> 2
-# 285| SubscriptExpr
-#-----| -> DeclRefExpr
+# 285| b
+#-----| -> &...
-# 285| AssignExpr
-#-----| -> DeclRefExpr
+# 285| ...[...]
+#-----| -> -
-# 285| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 285| setter for ... = ...
+#-----| -> b
-# 285| DeclRefExpr
-#-----| -> InOutExpr
+# 285| 2
+#-----| -> ...[...]
-# 285| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 285| &...
+#-----| -> 1
-# 285| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 285| b
+#-----| -> &...
-# 285| SubscriptExpr
-#-----| -> LoadExpr
+# 285| (Int) ...
+#-----| -> 1
-# 285| BinaryExpr
-#-----| -> AssignExpr
+# 285| getter for ...[...]
+#-----| -> (Int) ...
-# 285| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 285| ... call to - ...
+#-----| -> setter for ... = ...
-# 285| DeclRefExpr
-#-----| -> TypeExpr
+# 285| 1
+#-----| -> getter for ...[...]
-# 285| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 285| -
+#-----| -> Int.Type
-# 285| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 285| Int.Type
+#-----| -> call to -
-# 285| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 285| call to -
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 286| DeclRefExpr
-#-----| -> InOutExpr
+# 285| 1
+#-----| -> ... call to - ...
-# 286| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 286| &...
+#-----| -> 3
-# 286| SubscriptExpr
-#-----| -> DeclRefExpr
+# 286| b
+#-----| -> &...
-# 286| AssignExpr
-#-----| -> DeclRefExpr
+# 286| ...[...]
+#-----| -> *
-# 286| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 286| setter for ... = ...
+#-----| -> b
-# 286| DeclRefExpr
-#-----| -> InOutExpr
+# 286| 3
+#-----| -> ...[...]
-# 286| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 286| &...
+#-----| -> 2
-# 286| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 286| b
+#-----| -> &...
-# 286| SubscriptExpr
-#-----| -> LoadExpr
+# 286| (Int) ...
+#-----| -> 1
-# 286| BinaryExpr
-#-----| -> AssignExpr
+# 286| getter for ...[...]
+#-----| -> (Int) ...
-# 286| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 286| ... call to * ...
+#-----| -> setter for ... = ...
-# 286| DeclRefExpr
-#-----| -> TypeExpr
+# 286| 2
+#-----| -> getter for ...[...]
-# 286| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 286| *
+#-----| -> Int.Type
-# 286| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 286| Int.Type
+#-----| -> call to *
-# 286| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 286| call to *
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 287| DeclRefExpr
-#-----| -> InOutExpr
+# 286| 1
+#-----| -> ... call to * ...
-# 287| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 287| &...
+#-----| -> 4
-# 287| SubscriptExpr
-#-----| -> DeclRefExpr
+# 287| b
+#-----| -> &...
-# 287| AssignExpr
-#-----| -> DeclRefExpr
+# 287| ...[...]
+#-----| -> /
-# 287| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 287| setter for ... = ...
+#-----| -> b
-# 287| DeclRefExpr
-#-----| -> InOutExpr
+# 287| 4
+#-----| -> ...[...]
-# 287| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 287| &...
+#-----| -> 3
-# 287| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 287| b
+#-----| -> &...
-# 287| SubscriptExpr
-#-----| -> LoadExpr
+# 287| (Int) ...
+#-----| -> 1
-# 287| BinaryExpr
-#-----| -> AssignExpr
+# 287| getter for ...[...]
+#-----| -> (Int) ...
-# 287| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 287| ... call to / ...
+#-----| -> setter for ... = ...
-# 287| DeclRefExpr
-#-----| -> TypeExpr
+# 287| 3
+#-----| -> getter for ...[...]
-# 287| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 287| /
+#-----| -> Int.Type
-# 287| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 287| Int.Type
+#-----| -> call to /
-# 287| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 287| call to /
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 288| DeclRefExpr
-#-----| -> InOutExpr
+# 287| 1
+#-----| -> ... call to / ...
-# 288| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 288| &...
+#-----| -> 5
-# 288| SubscriptExpr
-#-----| -> DeclRefExpr
+# 288| b
+#-----| -> &...
-# 288| AssignExpr
-#-----| -> DeclRefExpr
+# 288| ...[...]
+#-----| -> %
-# 288| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 288| setter for ... = ...
+#-----| -> b
-# 288| DeclRefExpr
-#-----| -> InOutExpr
+# 288| 5
+#-----| -> ...[...]
-# 288| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 288| &...
+#-----| -> 4
-# 288| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 288| b
+#-----| -> &...
-# 288| SubscriptExpr
-#-----| -> LoadExpr
+# 288| (Int) ...
+#-----| -> 1
-# 288| BinaryExpr
-#-----| -> AssignExpr
+# 288| getter for ...[...]
+#-----| -> (Int) ...
-# 288| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 288| ... call to % ...
+#-----| -> setter for ... = ...
-# 288| DeclRefExpr
-#-----| -> TypeExpr
+# 288| 4
+#-----| -> getter for ...[...]
-# 288| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 288| %
+#-----| -> Int.Type
-# 288| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 288| Int.Type
+#-----| -> call to %
-# 288| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 288| call to %
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 289| DeclRefExpr
-#-----| -> InOutExpr
+# 288| 1
+#-----| -> ... call to % ...
-# 289| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 289| &...
+#-----| -> 6
-# 289| SubscriptExpr
-#-----| -> DeclRefExpr
+# 289| b
+#-----| -> &...
-# 289| AssignExpr
-#-----| -> DeclRefExpr
+# 289| ...[...]
+#-----| -> &
-# 289| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 289| setter for ... = ...
+#-----| -> b
-# 289| DeclRefExpr
-#-----| -> InOutExpr
+# 289| 6
+#-----| -> ...[...]
-# 289| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 289| &...
+#-----| -> 5
-# 289| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 289| b
+#-----| -> &...
-# 289| SubscriptExpr
-#-----| -> LoadExpr
+# 289| (Int) ...
+#-----| -> 1
-# 289| BinaryExpr
-#-----| -> AssignExpr
+# 289| getter for ...[...]
+#-----| -> (Int) ...
-# 289| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 289| ... call to & ...
+#-----| -> setter for ... = ...
-# 289| DeclRefExpr
-#-----| -> TypeExpr
+# 289| 5
+#-----| -> getter for ...[...]
-# 289| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 289| &
+#-----| -> Int.Type
-# 289| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 289| Int.Type
+#-----| -> call to &
-# 289| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 289| call to &
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 290| DeclRefExpr
-#-----| -> InOutExpr
+# 289| 1
+#-----| -> ... call to & ...
-# 290| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 290| &...
+#-----| -> 7
-# 290| SubscriptExpr
-#-----| -> DeclRefExpr
+# 290| b
+#-----| -> &...
-# 290| AssignExpr
-#-----| -> DeclRefExpr
+# 290| ...[...]
+#-----| -> |
-# 290| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 290| setter for ... = ...
+#-----| -> b
-# 290| DeclRefExpr
-#-----| -> InOutExpr
+# 290| 7
+#-----| -> ...[...]
-# 290| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 290| &...
+#-----| -> 6
-# 290| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 290| b
+#-----| -> &...
-# 290| SubscriptExpr
-#-----| -> LoadExpr
+# 290| (Int) ...
+#-----| -> 1
-# 290| BinaryExpr
-#-----| -> AssignExpr
+# 290| getter for ...[...]
+#-----| -> (Int) ...
-# 290| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 290| ... call to | ...
+#-----| -> setter for ... = ...
-# 290| DeclRefExpr
-#-----| -> TypeExpr
+# 290| 6
+#-----| -> getter for ...[...]
-# 290| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 290| Int.Type
+#-----| -> call to |
-# 290| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 290| call to |
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 290| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 290| |
+#-----| -> Int.Type
-# 291| DeclRefExpr
-#-----| -> InOutExpr
+# 290| 1
+#-----| -> ... call to | ...
-# 291| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 291| &...
+#-----| -> 8
-# 291| SubscriptExpr
-#-----| -> DeclRefExpr
+# 291| b
+#-----| -> &...
-# 291| AssignExpr
-#-----| -> DeclRefExpr
+# 291| ...[...]
+#-----| -> ^
-# 291| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 291| setter for ... = ...
+#-----| -> b
-# 291| DeclRefExpr
-#-----| -> InOutExpr
+# 291| 8
+#-----| -> ...[...]
-# 291| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 291| &...
+#-----| -> 7
-# 291| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 291| b
+#-----| -> &...
-# 291| SubscriptExpr
-#-----| -> LoadExpr
+# 291| (Int) ...
+#-----| -> 1
-# 291| BinaryExpr
-#-----| -> AssignExpr
+# 291| getter for ...[...]
+#-----| -> (Int) ...
-# 291| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 291| ... call to ^ ...
+#-----| -> setter for ... = ...
-# 291| DeclRefExpr
-#-----| -> TypeExpr
+# 291| 7
+#-----| -> getter for ...[...]
-# 291| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 291| Int.Type
+#-----| -> call to ^
-# 291| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 291| ^
+#-----| -> Int.Type
-# 291| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 291| call to ^
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 292| DeclRefExpr
-#-----| -> InOutExpr
+# 291| 1
+#-----| -> ... call to ^ ...
-# 292| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 292| &...
+#-----| -> 9
-# 292| SubscriptExpr
-#-----| -> DeclRefExpr
+# 292| b
+#-----| -> &...
-# 292| AssignExpr
-#-----| -> DeclRefExpr
+# 292| ...[...]
+#-----| -> <<
-# 292| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 292| setter for ... = ...
+#-----| -> b
-# 292| DeclRefExpr
-#-----| -> InOutExpr
+# 292| 9
+#-----| -> ...[...]
-# 292| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 292| &...
+#-----| -> 8
-# 292| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 292| b
+#-----| -> &...
-# 292| SubscriptExpr
-#-----| -> LoadExpr
+# 292| (Int) ...
+#-----| -> 1
-# 292| BinaryExpr
-#-----| -> AssignExpr
+# 292| getter for ...[...]
+#-----| -> (Int) ...
-# 292| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 292| ... call to << ...
+#-----| -> setter for ... = ...
-# 292| DeclRefExpr
-#-----| -> TypeExpr
+# 292| 8
+#-----| -> getter for ...[...]
-# 292| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 292| <<
+#-----| -> Int.Type
-# 292| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 292| Int.Type
+#-----| -> call to <<
-# 292| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 292| call to <<
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 293| DeclRefExpr
-#-----| -> InOutExpr
+# 292| 1
+#-----| -> ... call to << ...
-# 293| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 293| &...
+#-----| -> 10
-# 293| SubscriptExpr
-#-----| -> DeclRefExpr
+# 293| b
+#-----| -> &...
-# 293| AssignExpr
-#-----| -> TuplePattern
+# 293| ...[...]
+#-----| -> >>
-# 293| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 293| setter for ... = ...
+#-----| -> (...)
-# 293| DeclRefExpr
-#-----| -> InOutExpr
+# 293| 10
+#-----| -> ...[...]
-# 293| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 293| &...
+#-----| -> 9
-# 293| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 293| b
+#-----| -> &...
-# 293| SubscriptExpr
-#-----| -> LoadExpr
+# 293| (Int) ...
+#-----| -> 1
-# 293| BinaryExpr
-#-----| -> AssignExpr
+# 293| getter for ...[...]
+#-----| -> (Int) ...
-# 293| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 293| ... call to >> ...
+#-----| -> setter for ... = ...
-# 293| DeclRefExpr
-#-----| -> TypeExpr
+# 293| 9
+#-----| -> getter for ...[...]
-# 293| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 293| >>
+#-----| -> Int.Type
-# 293| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 293| Int.Type
+#-----| -> call to >>
-# 293| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 293| call to >>
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> b
-# 295| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 293| 1
+#-----| -> ... call to >> ...
-# 295| TuplePattern
-#-----| -> NamedPattern
+# 295| var ... = ...
+#-----| -> a1
-# 295| ConcreteVarDecl
-#-----| -> ConcreteVarDecl
+# 295| (...)
+#-----| -> a1
-# 295| NamedPattern
-#-----| -> DeclRefExpr
+# 295| a1
+#-----| -> tupleWithA
-# 295| ConcreteVarDecl
-#-----| -> ConcreteVarDecl
+# 295| a1
+#-----| -> a2
-# 295| ConcreteVarDecl
-#-----| -> ConcreteVarDecl
+# 295| a2
+#-----| -> a3
-# 295| ConcreteVarDecl
-#-----| -> ConcreteVarDecl
+# 295| a3
+#-----| -> a4
-# 295| ConcreteVarDecl
-#-----| -> DeclRefExpr
+# 295| a4
+#-----| -> a5
-# 295| DeclRefExpr
-#-----| -> LoadExpr
+# 295| a5
+#-----| -> +
-# 295| LoadExpr
-#-----| -> PatternBindingDecl
+# 295| ((Int, Int, Int, Int, Int)) ...
+#-----| -> var ... = ...
-# 296| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 295| tupleWithA
+#-----| -> ((Int, Int, Int, Int, Int)) ...
-# 296| TupleExpr
-#-----| -> ReturnStmt
+# 296| return ...
+#-----| return -> exit testSubscriptExpr (normal)
-# 296| DeclRefExpr
-#-----| -> DeclRefExpr
+# 296| (...)
+#-----| -> return ...
-# 296| BinaryExpr
-#-----| -> DeclRefExpr
+# 296| a1
+#-----| -> b
-# 296| DeclRefExpr
-#-----| -> TypeExpr
+# 296| ... call to + ...
+#-----| -> +
-# 296| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 296| +
+#-----| -> Int.Type
-# 296| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 296| Int.Type
+#-----| -> call to +
-# 296| DeclRefExpr
-#-----| -> InOutExpr
+# 296| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a1
-# 296| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 296| &...
+#-----| -> 0
-# 296| LoadExpr
-#-----| -> BinaryExpr
+# 296| b
+#-----| -> &...
-# 296| SubscriptExpr
-#-----| -> LoadExpr
+# 296| (Int) ...
+#-----| -> ... call to + ...
-# 296| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 296| getter for ...[...]
+#-----| -> (Int) ...
-# 296| DeclRefExpr
-#-----| -> DeclRefExpr
+# 296| 0
+#-----| -> getter for ...[...]
-# 296| BinaryExpr
-#-----| -> DeclRefExpr
+# 296| a2
+#-----| -> b
-# 296| DeclRefExpr
-#-----| -> TypeExpr
+# 296| ... call to + ...
+#-----| -> +
-# 296| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 296| +
+#-----| -> Int.Type
-# 296| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 296| Int.Type
+#-----| -> call to +
-# 296| DeclRefExpr
-#-----| -> InOutExpr
+# 296| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a2
-# 296| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 296| &...
+#-----| -> 1
-# 296| LoadExpr
-#-----| -> BinaryExpr
+# 296| b
+#-----| -> &...
-# 296| SubscriptExpr
-#-----| -> LoadExpr
+# 296| (Int) ...
+#-----| -> ... call to + ...
-# 296| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 296| getter for ...[...]
+#-----| -> (Int) ...
-# 296| DeclRefExpr
-#-----| -> DeclRefExpr
+# 296| 1
+#-----| -> getter for ...[...]
-# 296| BinaryExpr
-#-----| -> DeclRefExpr
+# 296| a3
+#-----| -> b
-# 296| DeclRefExpr
-#-----| -> TypeExpr
+# 296| ... call to + ...
+#-----| -> +
-# 296| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 296| +
+#-----| -> Int.Type
-# 296| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 296| Int.Type
+#-----| -> call to +
-# 296| DeclRefExpr
-#-----| -> InOutExpr
+# 296| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a3
-# 296| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 296| &...
+#-----| -> 2
-# 296| LoadExpr
-#-----| -> BinaryExpr
+# 296| b
+#-----| -> &...
-# 296| SubscriptExpr
-#-----| -> LoadExpr
+# 296| (Int) ...
+#-----| -> ... call to + ...
-# 296| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 296| getter for ...[...]
+#-----| -> (Int) ...
-# 296| DeclRefExpr
-#-----| -> DeclRefExpr
+# 296| 2
+#-----| -> getter for ...[...]
-# 296| BinaryExpr
-#-----| -> DeclRefExpr
+# 296| a4
+#-----| -> b
-# 296| DeclRefExpr
-#-----| -> TypeExpr
+# 296| ... call to + ...
+#-----| -> +
-# 296| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 296| +
+#-----| -> Int.Type
-# 296| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 296| Int.Type
+#-----| -> call to +
-# 296| DeclRefExpr
-#-----| -> InOutExpr
+# 296| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a4
-# 296| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 296| &...
+#-----| -> 3
-# 296| LoadExpr
-#-----| -> BinaryExpr
+# 296| b
+#-----| -> &...
-# 296| SubscriptExpr
-#-----| -> LoadExpr
+# 296| (Int) ...
+#-----| -> ... call to + ...
-# 296| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 296| getter for ...[...]
+#-----| -> (Int) ...
-# 296| DeclRefExpr
-#-----| -> DeclRefExpr
+# 296| 3
+#-----| -> getter for ...[...]
-# 296| BinaryExpr
-#-----| -> TupleExpr
+# 296| a5
+#-----| -> b
-# 296| DeclRefExpr
-#-----| -> TypeExpr
+# 296| ... call to + ...
+#-----| -> (...)
-# 296| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 296| +
+#-----| -> Int.Type
-# 296| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 296| Int.Type
+#-----| -> call to +
-# 296| DeclRefExpr
-#-----| -> InOutExpr
+# 296| call to +
+#-----| exception -> exit testSubscriptExpr (normal)
+#-----| -> a5
-# 296| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 296| &...
+#-----| -> 4
-# 296| LoadExpr
-#-----| -> BinaryExpr
+# 296| b
+#-----| -> &...
-# 296| SubscriptExpr
-#-----| -> LoadExpr
+# 296| (Int) ...
+#-----| -> ... call to + ...
-# 296| IntegerLiteralExpr
-#-----| -> SubscriptExpr
+# 296| getter for ...[...]
+#-----| -> (Int) ...
-# 299| enter ConcreteFuncDecl
-#-----| -> WhileStmt
+# 296| 4
+#-----| -> getter for ...[...]
-# 299| exit ConcreteFuncDecl
+# 299| enter loop1
+#-----| -> while ... { ... }
-# 299| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 299| exit loop1
-# 300| WhileStmt
-#-----| -> DeclRefExpr
+# 299| exit loop1 (normal)
+#-----| -> exit loop1
-# 300| DeclRefExpr
-#-----| -> LoadExpr
+# 300| while ... { ... }
+#-----| -> >=
-# 300| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 300| (Int) ...
+#-----| -> 0
-# 300| BinaryExpr
+# 300| x
+#-----| -> (Int) ...
+
+# 300| ... call to >= ...
#-----| -> StmtCondition
# 300| StmtCondition
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> DeclRefExpr
+#-----| false -> exit loop1 (normal)
+#-----| true -> print
-# 300| DeclRefExpr
-#-----| -> TypeExpr
+# 300| >=
+#-----| -> Int.Type
-# 300| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 300| Int.Type
+#-----| -> call to >=
-# 300| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 300| call to >=
+#-----| exception -> exit loop1 (normal)
+#-----| -> x
-# 300| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 300| 0
+#-----| -> ... call to >= ...
-# 301| DeclRefExpr
-#-----| -> DeclRefExpr
+# 301| print
+#-----| -> x
-# 301| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 301| call to print
+#-----| exception -> exit loop1 (normal)
+#-----| -> -=
-# 301| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 301| default separator
+#-----| -> default terminator
-# 301| DefaultArgumentExpr
-#-----| -> CallExpr
+# 301| default terminator
+#-----| -> call to print
-# 301| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 301| (Int) ...
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 301| DeclRefExpr
-#-----| -> LoadExpr
+# 301| (Any) ...
+#-----| -> [...]
-# 301| ErasureExpr
-#-----| -> ArrayExpr
+# 301| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 301| LoadExpr
-#-----| -> ErasureExpr
+# 301| [...]
+#-----| -> default separator
-# 301| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 301| [...]
+#-----| -> [...]
-# 302| DeclRefExpr
-#-----| -> InOutExpr
+# 301| x
+#-----| -> (Int) ...
-# 302| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 302| &...
+#-----| -> 1
-# 302| BinaryExpr
-#-----| -> DeclRefExpr
+# 302| x
+#-----| -> &...
-# 302| DeclRefExpr
-#-----| -> TypeExpr
+# 302| ... call to -= ...
+#-----| -> >=
-# 302| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 302| -=
+#-----| -> Int.Type
-# 302| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 302| Int.Type
+#-----| -> call to -=
-# 302| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 302| call to -=
+#-----| exception -> exit loop1 (normal)
+#-----| -> x
-# 306| enter ConcreteFuncDecl
-#-----| -> WhileStmt
+# 302| 1
+#-----| -> ... call to -= ...
-# 306| exit ConcreteFuncDecl
+# 306| enter loop2
+#-----| -> while ... { ... }
-# 306| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 306| exit loop2
-# 307| WhileStmt
-#-----| -> DeclRefExpr
+# 306| exit loop2 (normal)
+#-----| -> exit loop2
-# 307| DeclRefExpr
-#-----| -> LoadExpr
+# 307| while ... { ... }
+#-----| -> >=
-# 307| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 307| (Int) ...
+#-----| -> 0
-# 307| BinaryExpr
+# 307| x
+#-----| -> (Int) ...
+
+# 307| ... call to >= ...
#-----| -> StmtCondition
# 307| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+#-----| true -> print
+#-----| false -> print
-# 307| DeclRefExpr
-#-----| -> TypeExpr
+# 307| >=
+#-----| -> Int.Type
-# 307| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 307| Int.Type
+#-----| -> call to >=
-# 307| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 307| call to >=
+#-----| exception -> exit loop2 (normal)
+#-----| -> x
-# 307| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 307| 0
+#-----| -> ... call to >= ...
-# 308| DeclRefExpr
-#-----| -> DeclRefExpr
+# 308| print
+#-----| -> x
-# 308| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 308| call to print
+#-----| exception -> exit loop2 (normal)
+#-----| -> -=
-# 308| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 308| default separator
+#-----| -> default terminator
-# 308| DefaultArgumentExpr
-#-----| -> CallExpr
+# 308| default terminator
+#-----| -> call to print
-# 308| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 308| (Int) ...
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 308| DeclRefExpr
-#-----| -> LoadExpr
+# 308| (Any) ...
+#-----| -> [...]
-# 308| ErasureExpr
-#-----| -> ArrayExpr
+# 308| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 308| LoadExpr
-#-----| -> ErasureExpr
+# 308| [...]
+#-----| -> default separator
-# 308| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 308| [...]
+#-----| -> [...]
-# 309| DeclRefExpr
-#-----| -> InOutExpr
+# 308| x
+#-----| -> (Int) ...
-# 309| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 309| &...
+#-----| -> 1
-# 309| BinaryExpr
-#-----| -> IfStmt
+# 309| x
+#-----| -> &...
-# 309| DeclRefExpr
-#-----| -> TypeExpr
+# 309| ... call to -= ...
+#-----| -> if ... then { ... } else { ... }
-# 309| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 309| -=
+#-----| -> Int.Type
-# 309| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 309| Int.Type
+#-----| -> call to -=
-# 309| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 309| call to -=
+#-----| exception -> exit loop2 (normal)
+#-----| -> x
-# 310| IfStmt
-#-----| -> DeclRefExpr
+# 309| 1
+#-----| -> ... call to -= ...
-# 310| DeclRefExpr
-#-----| -> LoadExpr
+# 310| if ... then { ... } else { ... }
+#-----| -> >
-# 310| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 310| (Int) ...
+#-----| -> 100
-# 310| BinaryExpr
+# 310| x
+#-----| -> (Int) ...
+
+# 310| ... call to > ...
#-----| -> StmtCondition
# 310| StmtCondition
-#-----| true -> BreakStmt
-#-----| false -> IfStmt
+#-----| true -> break
+#-----| false -> if ... then { ... }
-# 310| DeclRefExpr
-#-----| -> TypeExpr
+# 310| >
+#-----| -> Int.Type
-# 310| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 310| Int.Type
+#-----| -> call to >
-# 310| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 310| call to >
+#-----| exception -> exit loop2 (normal)
+#-----| -> x
-# 310| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 310| 100
+#-----| -> ... call to > ...
-# 311| BreakStmt
-#-----| -> DeclRefExpr
+# 311| break
+#-----| -> print
-# 313| IfStmt
-#-----| -> DeclRefExpr
+# 313| if ... then { ... }
+#-----| -> >
-# 313| DeclRefExpr
-#-----| -> LoadExpr
+# 313| (Int) ...
+#-----| -> 50
-# 313| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 313| x
+#-----| -> (Int) ...
-# 313| BinaryExpr
+# 313| ... call to > ...
#-----| -> StmtCondition
# 313| StmtCondition
-#-----| true -> ContinueStmt
-#-----| false -> DeclRefExpr
+#-----| true -> continue
+#-----| false -> print
-# 313| DeclRefExpr
-#-----| -> TypeExpr
+# 313| >
+#-----| -> Int.Type
-# 313| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 313| Int.Type
+#-----| -> call to >
-# 313| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 313| call to >
+#-----| exception -> exit loop2 (normal)
+#-----| -> x
-# 313| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 313| 50
+#-----| -> ... call to > ...
-# 314| ContinueStmt
-#-----| continue -> DeclRefExpr
+# 314| continue
+#-----| continue -> >=
-# 316| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 316| print
+#-----| -> Iter
-# 316| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 316| call to print
+#-----| exception -> exit loop2 (normal)
+#-----| -> >=
-# 316| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 316| default separator
+#-----| -> default terminator
-# 316| DefaultArgumentExpr
-#-----| -> CallExpr
+# 316| default terminator
+#-----| -> call to print
-# 316| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 316| (Any) ...
+#-----| -> [...]
-# 316| ErasureExpr
-#-----| -> ArrayExpr
+# 316| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 316| StringLiteralExpr
-#-----| -> ErasureExpr
+# 316| Iter
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 316| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 316| [...]
+#-----| -> default separator
-# 318| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 316| [...]
+#-----| -> [...]
-# 318| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 318| print
+#-----| -> Done
-# 318| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 318| call to print
+#-----| exception -> exit loop2 (normal)
-# 318| DefaultArgumentExpr
-#-----| -> CallExpr
+# 318| default separator
+#-----| -> default terminator
-# 318| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 318| default terminator
+#-----| -> call to print
-# 318| ErasureExpr
-#-----| -> ArrayExpr
+# 318| (Any) ...
+#-----| -> [...]
-# 318| StringLiteralExpr
-#-----| -> ErasureExpr
+# 318| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 318| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 318| Done
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 321| enter ConcreteFuncDecl
-#-----| -> WhileStmt
+# 318| [...]
+#-----| -> default separator
-# 321| exit ConcreteFuncDecl
+# 318| [...]
+#-----| -> [...]
-# 321| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 321| enter labeledLoop
+#-----| -> while ... { ... }
-# 322| WhileStmt
-#-----| -> DeclRefExpr
+# 321| exit labeledLoop
-# 322| DeclRefExpr
-#-----| -> LoadExpr
+# 321| exit labeledLoop (normal)
+#-----| -> exit labeledLoop
-# 322| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 322| while ... { ... }
+#-----| -> >=
-# 322| BinaryExpr
+# 322| (Int) ...
+#-----| -> 0
+
+# 322| x
+#-----| -> (Int) ...
+
+# 322| ... call to >= ...
#-----| -> StmtCondition
# 322| StmtCondition
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> WhileStmt
+#-----| false -> exit labeledLoop (normal)
+#-----| true -> while ... { ... }
-# 322| DeclRefExpr
-#-----| -> TypeExpr
+# 322| >=
+#-----| -> Int.Type
-# 322| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 322| Int.Type
+#-----| -> call to >=
-# 322| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 322| call to >=
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> x
-# 322| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 322| 0
+#-----| -> ... call to >= ...
-# 323| WhileStmt
-#-----| -> DeclRefExpr
+# 323| while ... { ... }
+#-----| -> >=
-# 323| DeclRefExpr
-#-----| -> LoadExpr
+# 323| (Int) ...
+#-----| -> 0
-# 323| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 323| x
+#-----| -> (Int) ...
-# 323| BinaryExpr
+# 323| ... call to >= ...
#-----| -> StmtCondition
# 323| StmtCondition
-#-----| true -> DeclRefExpr
-#-----| false -> DeclRefExpr
+#-----| true -> print
+#-----| false -> print
-# 323| DeclRefExpr
-#-----| -> TypeExpr
+# 323| >=
+#-----| -> Int.Type
-# 323| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 323| Int.Type
+#-----| -> call to >=
-# 323| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 323| call to >=
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> x
-# 323| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 323| 0
+#-----| -> ... call to >= ...
-# 324| DeclRefExpr
-#-----| -> DeclRefExpr
+# 324| print
+#-----| -> x
-# 324| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 324| call to print
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> -=
-# 324| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 324| default separator
+#-----| -> default terminator
-# 324| DefaultArgumentExpr
-#-----| -> CallExpr
+# 324| default terminator
+#-----| -> call to print
-# 324| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 324| (Int) ...
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 324| DeclRefExpr
-#-----| -> LoadExpr
+# 324| (Any) ...
+#-----| -> [...]
-# 324| ErasureExpr
-#-----| -> ArrayExpr
+# 324| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 324| LoadExpr
-#-----| -> ErasureExpr
+# 324| [...]
+#-----| -> default separator
-# 324| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 324| [...]
+#-----| -> [...]
-# 325| DeclRefExpr
-#-----| -> InOutExpr
+# 324| x
+#-----| -> (Int) ...
-# 325| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 325| &...
+#-----| -> 1
-# 325| BinaryExpr
-#-----| -> IfStmt
+# 325| x
+#-----| -> &...
-# 325| DeclRefExpr
-#-----| -> TypeExpr
+# 325| ... call to -= ...
+#-----| -> if ... then { ... } else { ... }
-# 325| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 325| -=
+#-----| -> Int.Type
-# 325| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 325| Int.Type
+#-----| -> call to -=
-# 325| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 325| call to -=
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> x
-# 326| IfStmt
-#-----| -> DeclRefExpr
+# 325| 1
+#-----| -> ... call to -= ...
-# 326| DeclRefExpr
-#-----| -> LoadExpr
+# 326| if ... then { ... } else { ... }
+#-----| -> >
-# 326| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 326| (Int) ...
+#-----| -> 100
-# 326| BinaryExpr
+# 326| x
+#-----| -> (Int) ...
+
+# 326| ... call to > ...
#-----| -> StmtCondition
# 326| StmtCondition
-#-----| true -> BreakStmt
-#-----| false -> IfStmt
+#-----| true -> break outer
+#-----| false -> if ... then { ... }
-# 326| DeclRefExpr
-#-----| -> TypeExpr
+# 326| >
+#-----| -> Int.Type
-# 326| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 326| Int.Type
+#-----| -> call to >
-# 326| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 326| call to >
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> x
-# 326| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 326| 100
+#-----| -> ... call to > ...
-# 327| BreakStmt
-#-----| -> exit ConcreteFuncDecl (normal)
+# 327| break outer
+#-----| -> exit labeledLoop (normal)
-# 329| IfStmt
-#-----| -> DeclRefExpr
+# 329| if ... then { ... }
+#-----| -> >
-# 329| DeclRefExpr
-#-----| -> LoadExpr
+# 329| (Int) ...
+#-----| -> 50
-# 329| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 329| x
+#-----| -> (Int) ...
-# 329| BinaryExpr
+# 329| ... call to > ...
#-----| -> StmtCondition
# 329| StmtCondition
-#-----| true -> ContinueStmt
-#-----| false -> DeclRefExpr
+#-----| true -> continue inner
+#-----| false -> print
-# 329| DeclRefExpr
-#-----| -> TypeExpr
+# 329| >
+#-----| -> Int.Type
-# 329| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 329| Int.Type
+#-----| -> call to >
-# 329| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 329| call to >
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> x
-# 329| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 329| 50
+#-----| -> ... call to > ...
-# 330| ContinueStmt
-#-----| continue -> DeclRefExpr
+# 330| continue inner
+#-----| continue -> >=
-# 332| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 332| print
+#-----| -> Iter
-# 332| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 332| call to print
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> >=
-# 332| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 332| default separator
+#-----| -> default terminator
-# 332| DefaultArgumentExpr
-#-----| -> CallExpr
+# 332| default terminator
+#-----| -> call to print
-# 332| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 332| (Any) ...
+#-----| -> [...]
-# 332| ErasureExpr
-#-----| -> ArrayExpr
+# 332| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 332| StringLiteralExpr
-#-----| -> ErasureExpr
+# 332| Iter
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 332| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 332| [...]
+#-----| -> default separator
-# 334| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 332| [...]
+#-----| -> [...]
-# 334| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 334| print
+#-----| -> Done
-# 334| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 334| call to print
+#-----| exception -> exit labeledLoop (normal)
+#-----| -> >=
-# 334| DefaultArgumentExpr
-#-----| -> CallExpr
+# 334| default separator
+#-----| -> default terminator
-# 334| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 334| default terminator
+#-----| -> call to print
-# 334| ErasureExpr
-#-----| -> ArrayExpr
+# 334| (Any) ...
+#-----| -> [...]
-# 334| StringLiteralExpr
-#-----| -> ErasureExpr
+# 334| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 334| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 334| Done
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 338| enter ConcreteFuncDecl
-#-----| -> RepeatWhileStmt
+# 334| [...]
+#-----| -> default separator
-# 338| exit ConcreteFuncDecl
+# 334| [...]
+#-----| -> [...]
-# 338| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 338| enter testRepeat
+#-----| -> repeat { ... } while ...
-# 339| RepeatWhileStmt
-#-----| -> DeclRefExpr
+# 338| exit testRepeat
-# 340| DeclRefExpr
-#-----| -> DeclRefExpr
+# 338| exit testRepeat (normal)
+#-----| -> exit testRepeat
-# 340| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 339| repeat { ... } while ...
+#-----| -> print
-# 340| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 340| print
+#-----| -> x
-# 340| DefaultArgumentExpr
-#-----| -> CallExpr
+# 340| call to print
+#-----| exception -> exit testRepeat (normal)
+#-----| -> -=
-# 340| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 340| default separator
+#-----| -> default terminator
-# 340| DeclRefExpr
-#-----| -> LoadExpr
+# 340| default terminator
+#-----| -> call to print
-# 340| ErasureExpr
-#-----| -> ArrayExpr
+# 340| (Int) ...
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 340| LoadExpr
-#-----| -> ErasureExpr
+# 340| (Any) ...
+#-----| -> [...]
-# 340| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 340| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 341| DeclRefExpr
-#-----| -> InOutExpr
+# 340| [...]
+#-----| -> default separator
-# 341| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 340| [...]
+#-----| -> [...]
-# 341| BinaryExpr
-#-----| -> DeclRefExpr
+# 340| x
+#-----| -> (Int) ...
-# 341| DeclRefExpr
-#-----| -> TypeExpr
+# 341| &...
+#-----| -> 1
-# 341| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 341| x
+#-----| -> &...
-# 341| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 341| ... call to -= ...
+#-----| -> >=
-# 341| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 341| -=
+#-----| -> Int.Type
-# 342| DeclRefExpr
-#-----| -> LoadExpr
+# 341| Int.Type
+#-----| -> call to -=
-# 342| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 341| call to -=
+#-----| exception -> exit testRepeat (normal)
+#-----| -> x
-# 342| BinaryExpr
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> DeclRefExpr
+# 341| 1
+#-----| -> ... call to -= ...
-# 342| DeclRefExpr
-#-----| -> TypeExpr
+# 342| (Int) ...
+#-----| -> 0
-# 342| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 342| x
+#-----| -> (Int) ...
-# 342| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 342| ... call to >= ...
+#-----| false -> exit testRepeat (normal)
+#-----| true -> print
-# 342| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 342| >=
+#-----| -> Int.Type
-# 345| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 342| Int.Type
+#-----| -> call to >=
-# 345| exit ConcreteFuncDecl
+# 342| call to >=
+#-----| exception -> exit testRepeat (normal)
+#-----| -> x
-# 345| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 342| 0
+#-----| -> ... call to >= ...
-# 346| PatternBindingDecl
-#-----| -> ConcreteVarDecl
+# 345| enter loop_with_identity_expr
+#-----| -> x
-# 346| ConcreteVarDecl
-#-----| -> WhileStmt
+# 345| exit loop_with_identity_expr
-# 346| NamedPattern
-#-----| -> IntegerLiteralExpr
+# 345| exit loop_with_identity_expr (normal)
+#-----| -> exit loop_with_identity_expr
-# 346| IntegerLiteralExpr
-#-----| -> PatternBindingDecl
+# 346| var ... = ...
+#-----| -> x
-# 347| WhileStmt
-#-----| -> DeclRefExpr
+# 346| x
+#-----| -> 0
-# 347| ParenExpr
+# 346| x
+#-----| -> while ... { ... }
+
+# 346| 0
+#-----| -> var ... = ...
+
+# 347| while ... { ... }
+#-----| -> <
+
+# 347| (...)
#-----| -> StmtCondition
# 347| StmtCondition
-#-----| false -> exit ConcreteFuncDecl (normal)
-#-----| true -> DeclRefExpr
+#-----| false -> exit loop_with_identity_expr (normal)
+#-----| true -> +=
-# 347| DeclRefExpr
-#-----| -> LoadExpr
+# 347| (Int) ...
+#-----| -> 10
-# 347| LoadExpr
-#-----| -> IntegerLiteralExpr
+# 347| x
+#-----| -> (Int) ...
-# 347| BinaryExpr
-#-----| -> ParenExpr
+# 347| ... call to < ...
+#-----| -> (...)
-# 347| DeclRefExpr
-#-----| -> TypeExpr
+# 347| <
+#-----| -> Int.Type
-# 347| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 347| Int.Type
+#-----| -> call to <
-# 347| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 347| call to <
+#-----| exception -> exit loop_with_identity_expr (normal)
+#-----| -> x
-# 347| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 347| 10
+#-----| -> ... call to < ...
-# 348| DeclRefExpr
-#-----| -> InOutExpr
+# 348| &...
+#-----| -> 1
-# 348| InOutExpr
-#-----| -> IntegerLiteralExpr
+# 348| x
+#-----| -> &...
-# 348| BinaryExpr
-#-----| -> DeclRefExpr
+# 348| ... call to += ...
+#-----| -> <
-# 348| DeclRefExpr
-#-----| -> TypeExpr
+# 348| +=
+#-----| -> Int.Type
-# 348| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 348| Int.Type
+#-----| -> call to +=
-# 348| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 348| call to +=
+#-----| exception -> exit loop_with_identity_expr (normal)
+#-----| -> x
-# 348| IntegerLiteralExpr
-#-----| -> BinaryExpr
+# 348| 1
+#-----| -> ... call to += ...
-# 353| enter AccessorDecl
+# 353| enter get
-# 353| exit AccessorDecl
+# 353| exit get
-# 353| exit AccessorDecl (normal)
-#-----| -> exit AccessorDecl
+# 353| exit get (normal)
+#-----| -> exit get
-# 354| enter ConstructorDecl
-#-----| -> DeclRefExpr
+# 354| enter deinit
+#-----| -> self
-# 354| exit ConstructorDecl
+# 354| exit deinit
-# 354| exit ConstructorDecl (normal)
-#-----| -> exit ConstructorDecl
+# 354| exit deinit (normal)
+#-----| -> exit deinit
-# 355| DeclRefExpr
-#-----| -> MemberRefExpr
+# 355| .c
+#-----| -> arg
-# 355| MemberRefExpr
-#-----| -> DeclRefExpr
+# 355| self
+#-----| -> .c
-# 355| AssignExpr
-#-----| -> ReturnStmt
+# 355| ... = ...
+#-----| -> return
-# 355| DeclRefExpr
-#-----| -> AssignExpr
+# 355| arg
+#-----| -> ... = ...
-# 356| ReturnStmt
-#-----| return -> exit ConstructorDecl (normal)
+# 356| return
+#-----| return -> exit deinit (normal)
-# 358| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 358| enter getOptional
+#-----| -> self
-# 358| exit ConcreteFuncDecl
+# 358| exit getOptional
-# 358| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 358| exit getOptional (normal)
+#-----| -> exit getOptional
-# 359| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 359| return ...
+#-----| return -> exit getOptional (normal)
-# 359| DeclRefExpr
-#-----| -> MemberRefExpr
+# 359| getter for .c
+#-----| -> return ...
-# 359| MemberRefExpr
-#-----| -> ReturnStmt
+# 359| self
+#-----| -> getter for .c
-# 363| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 363| enter testOptional
+#-----| -> getMyInt
-# 363| exit ConcreteFuncDecl
+# 363| exit testOptional
-# 363| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 363| exit testOptional (normal)
+#-----| -> exit testOptional
-# 364| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 364| return ...
+#-----| return -> exit testOptional (normal)
-# 364| DeclRefExpr
-#-----| -> BindOptionalExpr
+# 364| c
+#-----| -> ...?
-# 364| BindOptionalExpr
-#-----| -> DotSyntaxCallExpr
+# 364| ...?
+#-----| -> call to getOptional
-# 364| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 364| call to getOptional
+#-----| exception -> exit testOptional (normal)
+#-----| -> call to ...
-# 364| CallExpr
-#-----| -> BindOptionalExpr
+# 364| call to ...
+#-----| -> ...?
-# 364| BindOptionalExpr
-#-----| -> DotSyntaxCallExpr
+# 364| ...?
+#-----| -> call to getMyInt
-# 364| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> CallExpr
+# 364| call to getMyInt
+#-----| exception -> exit testOptional (normal)
+#-----| -> call to ...
-# 364| CallExpr
-#-----| -> InjectIntoOptionalExpr
-
-# 364| InjectIntoOptionalExpr
+# 364| (Int?) ...
#-----| -> OptionalEvaluationExpr
# 364| OptionalEvaluationExpr
-#-----| -> ReturnStmt
+#-----| -> return ...
-# 364| DeclRefExpr
-#-----| -> DeclRefExpr
+# 364| call to ...
+#-----| -> (Int?) ...
-# 364| DeclRefExpr
-#-----| -> DeclRefExpr
+# 364| getOptional
+#-----| -> c
-# 367| enter ConcreteFuncDecl
-#-----| -> NamedPattern
+# 364| getMyInt
+#-----| -> getOptional
-# 367| exit ConcreteFuncDecl
+# 367| enter testCapture
+#-----| -> z
-# 367| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 367| exit testCapture
-# 368| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 367| exit testCapture (normal)
+#-----| -> exit testCapture
-# 368| CaptureListExpr
-#-----| -> ReturnStmt
+# 368| return ...
+#-----| return -> exit testCapture (normal)
-# 368| ClosureExpr
-#-----| -> CaptureListExpr
+# 368| { ... }
+#-----| -> return ...
-# 368| NamedPattern
-#-----| -> DeclRefExpr
+# 368| { ... }
+#-----| -> { ... }
-# 368| PatternBindingDecl
-#-----| -> NamedPattern
+# 368| z
+#-----| -> +
-# 368| DeclRefExpr
-#-----| -> DeclRefExpr
+# 368| var ... = ...
+#-----| -> t
-# 368| BinaryExpr
-#-----| -> PatternBindingDecl
+# 368| x
+#-----| -> y
-# 368| DeclRefExpr
-#-----| -> TypeExpr
+# 368| ... call to + ...
+#-----| -> var ... = ...
-# 368| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 368| +
+#-----| -> Int.Type
-# 368| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 368| Int.Type
+#-----| -> call to +
-# 368| DeclRefExpr
-#-----| -> BinaryExpr
+# 368| call to +
+#-----| exception -> exit testCapture (normal)
+#-----| -> x
-# 368| NamedPattern
-#-----| -> StringLiteralExpr
+# 368| y
+#-----| -> ... call to + ...
-# 368| PatternBindingDecl
-#-----| -> ClosureExpr
+# 368| t
+#-----| -> literal
-# 368| StringLiteralExpr
-#-----| -> PatternBindingDecl
+# 368| var ... = ...
+#-----| -> { ... }
-# 373| enter ConcreteFuncDecl
-#-----| -> DeclRefExpr
+# 368| literal
+#-----| -> var ... = ...
-# 373| exit ConcreteFuncDecl
+# 373| enter testTupleElement
+#-----| -> +
-# 373| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 373| exit testTupleElement
-# 374| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 373| exit testTupleElement (normal)
+#-----| -> exit testTupleElement
-# 374| DeclRefExpr
-#-----| -> TupleElementExpr
+# 374| return ...
+#-----| return -> exit testTupleElement (normal)
-# 374| TupleElementExpr
-#-----| -> DeclRefExpr
+# 374| t
+#-----| -> .0
-# 374| BinaryExpr
-#-----| -> DeclRefExpr
+# 374| .0
+#-----| -> t
-# 374| BinaryExpr
-#-----| -> IntegerLiteralExpr
+# 374| ... call to + ...
+#-----| -> t
-# 374| BinaryExpr
-#-----| -> ReturnStmt
+# 374| ... call to + ...
+#-----| -> 1
-# 374| DeclRefExpr
-#-----| -> TypeExpr
+# 374| ... call to + ...
+#-----| -> return ...
-# 374| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 374| +
+#-----| -> Int.Type
-# 374| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 374| Int.Type
+#-----| -> call to +
-# 374| DeclRefExpr
-#-----| -> TupleElementExpr
+# 374| call to +
+#-----| exception -> exit testTupleElement (normal)
+#-----| -> t
-# 374| TupleElementExpr
-#-----| -> BinaryExpr
+# 374| t
+#-----| -> .1
-# 374| DeclRefExpr
-#-----| -> TypeExpr
+# 374| .1
+#-----| -> ... call to + ...
-# 374| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 374| +
+#-----| -> Int.Type
-# 374| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 374| Int.Type
+#-----| -> call to +
-# 374| DeclRefExpr
-#-----| -> TupleElementExpr
+# 374| call to +
+#-----| exception -> exit testTupleElement (normal)
+#-----| -> +
-# 374| TupleElementExpr
-#-----| -> BinaryExpr
+# 374| t
+#-----| -> .2
-# 374| DeclRefExpr
-#-----| -> TypeExpr
+# 374| .2
+#-----| -> ... call to + ...
-# 374| DotSyntaxCallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> DeclRefExpr
+# 374| +
+#-----| -> Int.Type
-# 374| TypeExpr
-#-----| -> DotSyntaxCallExpr
+# 374| Int.Type
+#-----| -> call to +
-# 374| TupleExpr
-#-----| -> TupleElementExpr
+# 374| call to +
+#-----| exception -> exit testTupleElement (normal)
+#-----| -> +
-# 374| TupleElementExpr
-#-----| -> BinaryExpr
+# 374| (...)
+#-----| -> .0
-# 374| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 374| .0
+#-----| -> ... call to + ...
-# 374| IntegerLiteralExpr
-#-----| -> IntegerLiteralExpr
+# 374| 1
+#-----| -> 2
-# 374| IntegerLiteralExpr
-#-----| -> TupleExpr
+# 374| 2
+#-----| -> 3
-# 377| CallExpr
-#-----| exception -> exit ConstructorDecl (normal)
+# 374| 3
+#-----| -> (...)
-# 377| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 377| #...
+#-----| -> #...
-# 377| MagicIdentifierLiteralExpr
-#-----| -> MagicIdentifierLiteralExpr
+# 377| #...
+#-----| -> #...
-# 377| MagicIdentifierLiteralExpr
-#-----| -> MagicIdentifierLiteralExpr
+# 377| #...
+#-----| -> #...
-# 377| MagicIdentifierLiteralExpr
-#-----| -> MagicIdentifierLiteralExpr
+# 377| #...
+#-----| -> call to _unimplementedInitializer
-# 377| MagicIdentifierLiteralExpr
-#-----| -> CallExpr
+# 377| _unimplementedInitializer
+#-----| -> cfg.Derived
-# 377| StringLiteralExpr
-#-----| -> MagicIdentifierLiteralExpr
+# 377| call to _unimplementedInitializer
+#-----| exception -> exit deinit (normal)
-# 377| enter ConstructorDecl
-#-----| -> DeclRefExpr
+# 377| cfg.Derived
+#-----| -> #...
-# 377| exit ConstructorDecl
+# 377| enter deinit
+#-----| -> _unimplementedInitializer
-# 377| exit ConstructorDecl (normal)
-#-----| -> exit ConstructorDecl
+# 377| exit deinit
-# 378| enter ConstructorDecl
+# 377| exit deinit (normal)
+#-----| -> exit deinit
+
+# 378| enter deinit
+#-----| -> call to ...
#-----| -> TBD (OtherConstructorDeclRefExpr)
-# 378| exit ConstructorDecl
+# 378| exit deinit
-# 378| exit ConstructorDecl (normal)
-#-----| -> exit ConstructorDecl
+# 378| exit deinit (normal)
+#-----| -> exit deinit
-# 379| SuperRefExpr
-#-----| -> DotSyntaxCallExpr
+# 379| super
+#-----| -> call to ...
-# 379| DotSyntaxCallExpr
-#-----| -> IntegerLiteralExpr
+# 379| call to ...
+#-----| -> 0
-# 379| CallExpr
-#-----| -> RebindSelfInConstructorExpr
+# 379| call to ...
+#-----| -> self = ...
-# 379| RebindSelfInConstructorExpr
-#-----| -> ReturnStmt
+# 379| self = ...
+#-----| -> return
+
+# 379| call to ...
+#-----| -> super
# 379| TBD (OtherConstructorDeclRefExpr)
-#-----| -> SuperRefExpr
+#-----| -> super
-# 379| IntegerLiteralExpr
-#-----| -> CallExpr
+# 379| 0
+#-----| -> call to ...
-# 380| ReturnStmt
-#-----| return -> exit ConstructorDecl (normal)
+# 380| return
+#-----| return -> exit deinit (normal)
-# 383| enter ConcreteFuncDecl
-#-----| -> DoStmt
+# 383| enter doWithoutCatch
+#-----| -> do { ... }
-# 383| exit ConcreteFuncDecl
+# 383| exit doWithoutCatch
-# 383| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 383| exit doWithoutCatch (normal)
+#-----| -> exit doWithoutCatch
-# 384| DoStmt
-#-----| -> DeclRefExpr
+# 384| do { ... }
+#-----| -> mightThrow
-# 385| TryExpr
-#-----| -> DeclRefExpr
+# 385| try ...
+#-----| -> print
-# 385| DeclRefExpr
-#-----| -> IntegerLiteralExpr
+# 385| mightThrow
+#-----| -> 0
-# 385| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
-#-----| -> TryExpr
+# 385| call to mightThrow
+#-----| exception -> exit doWithoutCatch (normal)
+#-----| -> try ...
-# 385| IntegerLiteralExpr
-#-----| -> CallExpr
+# 385| 0
+#-----| -> call to mightThrow
-# 386| DeclRefExpr
-#-----| -> StringLiteralExpr
+# 386| print
+#-----| -> Did not throw.
-# 386| CallExpr
-#-----| exception -> exit ConcreteFuncDecl (normal)
+# 386| call to print
+#-----| exception -> exit doWithoutCatch (normal)
-# 386| DefaultArgumentExpr
-#-----| -> DefaultArgumentExpr
+# 386| default separator
+#-----| -> default terminator
-# 386| DefaultArgumentExpr
-#-----| -> CallExpr
+# 386| default terminator
+#-----| -> call to print
-# 386| ArrayExpr
-#-----| -> VarargExpansionExpr
+# 386| (Any) ...
+#-----| -> [...]
-# 386| ErasureExpr
-#-----| -> ArrayExpr
+# 386| (TBD (ProtocolCompositionType)) ...
+#-----| -> [...]
-# 386| StringLiteralExpr
-#-----| -> ErasureExpr
+# 386| Did not throw.
+#-----| -> (Any) ...
+#-----| -> (TBD (ProtocolCompositionType)) ...
-# 386| VarargExpansionExpr
-#-----| -> DefaultArgumentExpr
+# 386| [...]
+#-----| -> default separator
-# 394| TBD (YieldStmt)
-#-----| -> exit AccessorDecl (normal)
+# 386| [...]
+#-----| -> [...]
-# 394| enter AccessorDecl
-
-# 394| enter AccessorDecl
-
-# 394| enter AccessorDecl
+# 394| enter (unnamed function decl)
+#-----| -> yield ...
#-----| -> TBD (YieldStmt)
-# 394| exit AccessorDecl
+# 394| enter get
-# 394| exit AccessorDecl
+# 394| enter set
-# 394| exit AccessorDecl
+# 394| exit (unnamed function decl)
-# 394| exit AccessorDecl (normal)
-#-----| -> exit AccessorDecl
+# 394| exit (unnamed function decl) (normal)
+#-----| -> exit (unnamed function decl)
-# 394| exit AccessorDecl (normal)
-#-----| -> exit AccessorDecl
+# 394| exit get
-# 394| exit AccessorDecl (normal)
-#-----| -> exit AccessorDecl
+# 394| exit get (normal)
+#-----| -> exit get
-# 395| enter ConstructorDecl
-#-----| -> DeclRefExpr
+# 394| exit set
-# 395| exit ConstructorDecl
+# 394| exit set (normal)
+#-----| -> exit set
-# 395| exit ConstructorDecl (normal)
-#-----| -> exit ConstructorDecl
+# 394| yield ...
+#-----| -> exit (unnamed function decl) (normal)
-# 396| DeclRefExpr
-#-----| -> MemberRefExpr
+# 394| TBD (YieldStmt)
+#-----| -> exit (unnamed function decl) (normal)
-# 396| MemberRefExpr
-#-----| -> IntegerLiteralExpr
+# 395| enter deinit
+#-----| -> self
-# 396| AssignExpr
-#-----| -> ReturnStmt
+# 395| exit deinit
-# 396| IntegerLiteralExpr
-#-----| -> AssignExpr
+# 395| exit deinit (normal)
+#-----| -> exit deinit
-# 397| ReturnStmt
-#-----| return -> exit ConstructorDecl (normal)
+# 396| .field
+#-----| -> 10
-# 399| enter DestructorDecl
-#-----| -> DeclRefExpr
+# 396| self
+#-----| -> .field
-# 399| exit DestructorDecl
+# 396| ... = ...
+#-----| -> return
-# 399| exit DestructorDecl (normal)
-#-----| -> exit DestructorDecl
+# 396| 10
+#-----| -> ... = ...
-# 400| DeclRefExpr
-#-----| -> MemberRefExpr
+# 397| return
+#-----| return -> exit deinit (normal)
-# 400| MemberRefExpr
-#-----| -> IntegerLiteralExpr
+# 399| enter init
+#-----| -> self
-# 400| AssignExpr
-#-----| -> exit DestructorDecl (normal)
+# 399| exit init
-# 400| IntegerLiteralExpr
-#-----| -> AssignExpr
+# 399| exit init (normal)
+#-----| -> exit init
-# 404| enter ConcreteFuncDecl
-#-----| -> StringLiteralExpr
+# 400| .field
+#-----| -> 0
-# 404| exit ConcreteFuncDecl
+# 400| self
+#-----| -> .field
-# 404| exit ConcreteFuncDecl (normal)
-#-----| -> exit ConcreteFuncDecl
+# 400| ... = ...
+#-----| -> exit init (normal)
-# 405| ReturnStmt
-#-----| return -> exit ConcreteFuncDecl (normal)
+# 400| 0
+#-----| -> ... = ...
-# 405| DictionaryExpr
-#-----| -> ReturnStmt
+# 404| enter dictionaryLiteral
+#-----| -> x
-# 405| StringLiteralExpr
-#-----| -> DeclRefExpr
+# 404| exit dictionaryLiteral
-# 405| TupleExpr
-#-----| -> StringLiteralExpr
+# 404| exit dictionaryLiteral (normal)
+#-----| -> exit dictionaryLiteral
-# 405| DeclRefExpr
-#-----| -> TupleExpr
+# 405| return ...
+#-----| return -> exit dictionaryLiteral (normal)
-# 405| StringLiteralExpr
-#-----| -> DeclRefExpr
+# 405| [...]
+#-----| -> return ...
-# 405| TupleExpr
-#-----| -> DictionaryExpr
+# 405| x
+#-----| -> x
-# 405| DeclRefExpr
-#-----| -> TupleExpr
+# 405| (...)
+#-----| -> y
+
+# 405| x
+#-----| -> (...)
+
+# 405| y
+#-----| -> y
+
+# 405| (...)
+#-----| -> [...]
+
+# 405| y
+#-----| -> (...)
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
new file mode 100644
index 00000000000..92fe3d7565c
--- /dev/null
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -0,0 +1,14 @@
+| file://:0:0:0:0 | Phi | test.swift:15:15:15:15 | t2 |
+| file://:0:0:0:0 | Phi | test.swift:21:15:21:15 | t1 |
+| test.swift:6:9:6:13 | WriteDef | test.swift:7:15:7:15 | t1 |
+| test.swift:7:15:7:15 | t1 | test.swift:8:10:8:10 | t1 |
+| test.swift:8:5:8:10 | WriteDef | test.swift:10:15:10:15 | t2 |
+| test.swift:8:10:8:10 | t1 | test.swift:8:5:8:10 | WriteDef |
+| test.swift:8:10:8:10 | t1 | test.swift:9:15:9:15 | t1 |
+| test.swift:9:15:9:15 | t1 | test.swift:11:8:11:8 | t1 |
+| test.swift:12:9:12:14 | WriteDef | test.swift:13:19:13:19 | t2 |
+| test.swift:12:14:12:14 | 0 | test.swift:12:9:12:14 | WriteDef |
+| test.swift:15:15:15:15 | t2 | test.swift:19:14:19:14 | t2 |
+| test.swift:17:10:17:10 | 0 | test.swift:17:5:17:10 | WriteDef |
+| test.swift:19:14:19:14 | t2 | test.swift:19:9:19:14 | WriteDef |
+| test.swift:19:14:19:14 | t2 | test.swift:19:14:19:14 | t2 |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.ql b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.ql
new file mode 100644
index 00000000000..04a547b939d
--- /dev/null
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.ql
@@ -0,0 +1,6 @@
+import swift
+import codeql.swift.dataflow.DataFlow
+
+from DataFlow::Node pred, DataFlow::Node succ
+where DataFlow::localFlowStep(pred, succ)
+select pred, succ
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
new file mode 100644
index 00000000000..d20fecb54d7
--- /dev/null
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -0,0 +1,22 @@
+func source() -> Int { return 0; }
+func sink(arg: Int) {}
+
+func intraprocedural_with_local_flow() -> Void {
+ var t2: Int
+ var t1: Int = source()
+ sink(arg: t1)
+ t2 = t1
+ sink(arg: t1)
+ sink(arg: t2)
+ if(t1 != 0) {
+ t2 = 0
+ sink(arg: t2)
+ }
+ sink(arg: t2)
+
+ t1 = 0;
+ while(false) {
+ t1 = t2
+ }
+ sink(arg: t1)
+}