diff --git a/powershell/codeql-extractor.yml b/powershell/codeql-extractor.yml
index c671f2be6341..1180dd447656 100644
--- a/powershell/codeql-extractor.yml
+++ b/powershell/codeql-extractor.yml
@@ -10,4 +10,5 @@ file_types:
display_name: powershellscripts
extensions:
- .ps1
- - .psd1
\ No newline at end of file
+ - .psd1
+ - .psm1
\ No newline at end of file
diff --git a/powershell/extractor/Semmle.Extraction.PowerShell.Standalone/Options.cs b/powershell/extractor/Semmle.Extraction.PowerShell.Standalone/Options.cs
index caf2c6f00125..934bf7f96e7a 100644
--- a/powershell/extractor/Semmle.Extraction.PowerShell.Standalone/Options.cs
+++ b/powershell/extractor/Semmle.Extraction.PowerShell.Standalone/Options.cs
@@ -74,7 +74,7 @@ public override void InvalidArgument(string argument)
///
/// List of extensions to include.
///
- public IList Extensions { get; } = new List() { ".ps1" };
+ public IList Extensions { get; } = new List() { ".ps1", ".psd1", ".psm1" };
///
/// Files/patterns to exclude.
diff --git a/powershell/extractor/Semmle.Extraction/Tuples.cs b/powershell/extractor/Semmle.Extraction/Tuples.cs
index 2cff4bfbdf1d..afe19295ee5b 100644
--- a/powershell/extractor/Semmle.Extraction/Tuples.cs
+++ b/powershell/extractor/Semmle.Extraction/Tuples.cs
@@ -30,7 +30,7 @@ internal static void folders(this System.IO.TextWriter trapFile, Folder folder,
public static void locations_default(this System.IO.TextWriter trapFile, SourceLocation label, Entities.File file, int startLine, int startCol, int endLine, int endCol)
{
- trapFile.WriteTuple("locations_default", label, file, startLine, startCol, endLine, endCol);
+ trapFile.WriteTuple("locations_default", label, file, startLine, startCol, endLine, endCol - 1);
}
}
}
diff --git a/powershell/ql/lib/powershell.qll b/powershell/ql/lib/powershell.qll
index 8bbfe93262ab..67ec61e3003c 100644
--- a/powershell/ql/lib/powershell.qll
+++ b/powershell/ql/lib/powershell.qll
@@ -1,85 +1 @@
-import semmle.code.powershell.File
-import semmle.code.powershell.Location
-import semmle.code.powershell.SourceLocation
-import semmle.code.powershell.Ast
-import semmle.code.powershell.Statement
-import semmle.code.powershell.Expression
-import semmle.code.powershell.CommandBase
-import semmle.code.powershell.AttributeBase
-import semmle.code.powershell.PipelineBase
-import semmle.code.powershell.PipelineChain
-import semmle.code.powershell.BaseConstantExpression
-import semmle.code.powershell.ConstantExpression
-import semmle.code.powershell.MemberExpressionBase
-import semmle.code.powershell.Attribute
-import semmle.code.powershell.NamedAttributeArgument
-import semmle.code.powershell.TypeConstraint
-import semmle.code.powershell.VariableExpression
-import semmle.code.powershell.ModuleSpecification
-import semmle.code.powershell.ParamBlock
-import semmle.code.powershell.NamedBlock
-import semmle.code.powershell.ScriptBlock
-import semmle.code.powershell.StringLiteral
-import semmle.code.powershell.AssignmentStatement
-import semmle.code.powershell.BinaryExpression
-import semmle.code.powershell.UnaryExpression
-import semmle.code.powershell.ScriptBlockExpr
-import semmle.code.powershell.TernaryExpression
-import semmle.code.powershell.UsingExpression
-import semmle.code.powershell.TrapStatement
-import semmle.code.powershell.StatementBlock
-import semmle.code.powershell.ArrayExpression
-import semmle.code.powershell.ArrayLiteral
-import semmle.code.powershell.CommandElement
-import semmle.code.powershell.Redirection
-import semmle.code.powershell.FileRedirection
-import semmle.code.powershell.MergingRedirection
-import semmle.code.powershell.LoopStmt
-import semmle.code.powershell.DoWhileStmt
-import semmle.code.powershell.DoUntilStmt
-import semmle.code.powershell.WhileStmt
-import semmle.code.powershell.ForStmt
-import semmle.code.powershell.ForEachStmt
-import semmle.code.powershell.GotoStmt
-import semmle.code.powershell.ContinueStmt
-import semmle.code.powershell.BreakStmt
-import semmle.code.powershell.ReturnStmt
-import semmle.code.powershell.UsingStmt
-import semmle.code.powershell.ThrowStmt
-import semmle.code.powershell.ErrorStmt
-import semmle.code.powershell.Type
-import semmle.code.powershell.Member
-import semmle.code.powershell.PropertyMember
-import semmle.code.powershell.Function
-import semmle.code.powershell.TryStmt
-import semmle.code.powershell.IfStmt
-import semmle.code.powershell.SwitchStmt
-import semmle.code.powershell.ExitStmt
-import semmle.code.powershell.LabeledStmt
-import semmle.code.powershell.DynamicStmt
-import semmle.code.powershell.DataStmt
-import semmle.code.powershell.Configuration
-import semmle.code.powershell.CatchClause
-import semmle.code.powershell.Command
-import semmle.code.powershell.CommandExpression
-import semmle.code.powershell.CommandParameter
-import semmle.code.powershell.ExpandableStringExpression
-import semmle.code.powershell.TypeExpression
-import semmle.code.powershell.ParenExpression
-import semmle.code.powershell.Chainable
-import semmle.code.powershell.Pipeline
-import semmle.code.powershell.StringConstantExpression
-import semmle.code.powershell.MemberExpr
-import semmle.code.powershell.InvokeMemberExpression
-import semmle.code.powershell.Call
-import semmle.code.powershell.ObjectCreation
-import semmle.code.powershell.SubExpression
-import semmle.code.powershell.ErrorExpr
-import semmle.code.powershell.ConvertExpr
-import semmle.code.powershell.IndexExpr
-import semmle.code.powershell.HashTable
-import semmle.code.powershell.SplitExpr
-import semmle.code.powershell.CommentEntity
-import semmle.code.powershell.Variable
-import semmle.code.powershell.internal.Internal::Public
-import semmle.code.powershell.ModuleManifest
\ No newline at end of file
+import semmle.code.powershell.ast.Ast
\ No newline at end of file
diff --git a/powershell/ql/lib/semmle/code/powershell/ApiGraphs.qll b/powershell/ql/lib/semmle/code/powershell/ApiGraphs.qll
index 7fe18c97f6e9..8634161e5a01 100644
--- a/powershell/ql/lib/semmle/code/powershell/ApiGraphs.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ApiGraphs.qll
@@ -271,7 +271,8 @@ module API {
this = Impl::MkMethodAccessNode(result) or
this = Impl::MkBackwardNode(result, _) or
this = Impl::MkForwardNode(result, _) or
- this = Impl::MkSinkNode(result)
+ this = Impl::MkSinkNode(result) or
+ this = Impl::MkNamespaceOfTypeNameNode(result)
}
/** Gets the location of this node. */
@@ -324,45 +325,6 @@ module API {
}
}
- /** A node representing a module/class object with epsilon edges to its descendents. */
- private class ModuleNode extends Node, Impl::MkModule {
- string qualifiedModule;
- int n;
-
- ModuleNode() { this = Impl::MkModule(qualifiedModule, n) }
-
- ModuleNode getNext() { result = Impl::MkModule(qualifiedModule, n + 1) }
-
- ModuleNode getPred() { result.getNext() = this }
-
- string getComponent() { result = qualifiedModule.splitAt(".", n) }
-
- string getModule() {
- not exists(this.getPred()) and
- result = this.getComponent()
- or
- result = this.getPred().getModule() + "." + this.getComponent()
- }
-
- override string toString() { result = "Module(" + this.getModule() + ")" }
- }
-
- /** A node representing instances of a module/class with epsilon edges to its ancestors. */
- private class InstanceUp extends Node, Impl::MkInstanceUp {
- /** Gets the module whose instances are represented by this API node. */
- string getType() { this = Impl::MkInstanceUp(result) }
-
- override string toString() { result = "ModuleInstanceUp(" + this.getType() + ")" }
- }
-
- /** A node representing instances of a module/class with epsilon edges to its descendents. */
- private class InstanceDownNode extends Node, Impl::MkInstanceDown {
- /** Gets the module whose instances are represented by this API node. */
- string getType() { this = Impl::MkInstanceDown(result) }
-
- override string toString() { result = "ModuleInstanceDown(" + this.getType() + ")" }
- }
-
/** A node corresponding to the method being invoked at a method call. */
class MethodAccessNode extends Node, Impl::MkMethodAccessNode {
override string toString() { result = "MethodAccessNode(" + this.asCall() + ")" }
@@ -378,6 +340,22 @@ module API {
override string toString() { result = "SinkNode(" + this.getInducingNode() + ")" }
}
+ private class UsingNode extends Node, Impl::MkUsingNode {
+ UsingStmt using; // TODO: This should really be the cfg node, I think
+
+ UsingNode() { this = Impl::MkUsingNode(using) }
+
+ override string toString() { result = "UsingNode(" + using + ")" }
+ }
+
+ private class NamespaceOfTypeNameNode extends Node, Impl::MkNamespaceOfTypeNameNode {
+ DataFlow::QualifiedTypeNameNode typeName;
+
+ NamespaceOfTypeNameNode() { this = Impl::MkNamespaceOfTypeNameNode(typeName) }
+
+ override string toString() { result = "NamespaceOfTypeNameNode(" + typeName + ")" }
+ }
+
/**
* An API entry point.
*
@@ -415,11 +393,15 @@ module API {
/** Gets the root node. */
Node root() { result instanceof RootNode }
- /**
- * Gets the node that represents the module with qualified
- * name `qualifiedModule`.
- */
- ModuleNode mod(string qualifiedModule, int n) { result = Impl::MkModule(qualifiedModule, n) }
+ bindingset[name]
+ pragma[inline_late]
+ Node namespace(string name) {
+ // This predicate is currently not 'inline_late' because 'n' can be an input or output
+ Impl::namespace(name, result)
+ }
+
+ pragma[inline]
+ Node getTopLevelMember(string name) { Impl::topLevelMember(name, result) }
/**
* Gets an unqualified call at the top-level with the given method name.
@@ -466,44 +448,14 @@ module API {
cached
private module Impl {
- private predicate isGacModule(string s) {
- s =
- [
- "System.Management.Automation",
- "Microsoft.Management.Infrastructure",
- "Microsoft.PowerShell.Security",
- "Microsoft.PowerShell.Commands.Management",
- "Microsoft.PowerShell.Commands.Utility"
- ]
- }
-
- private predicate isModule(string s, int n) {
- (
- any(UsingStmt using).getName() = s
- or
- any(Cmd cmd).getNamespaceQualifier() = s
- or
- any(TypeNameExpr tn).getName() = s
- or
- any(ModuleManifest manifest).getModuleName() = s
- or
- isGacModule(s)
- ) and
- exists(s.splitAt(".", n))
- }
-
cached
newtype TApiNode =
/** The root of the API graph. */
MkRoot() or
/** The method accessed at `call`, synthetically treated as a separate object. */
MkMethodAccessNode(DataFlow::CallNode call) or
- MkModule(string qualifiedModule, int n) { isModule(qualifiedModule, n) } or
- /** Instances of `mod` with epsilon edges to its ancestors. */
- MkInstanceUp(string qualifiedType) { exists(MkModule(qualifiedType, _)) } or
- /** Instances of `mod` with epsilon edges to its descendents, and to its upward node. */
- MkInstanceDown(string qualifiedType) { exists(MkModule(qualifiedType, _)) } or
- /** Intermediate node for following forward data flow. */
+ MkUsingNode(UsingStmt using) or
+ MkNamespaceOfTypeNameNode(DataFlow::QualifiedTypeNameNode typeName) or
MkForwardNode(DataFlow::LocalSourceNode node, TypeTracker t) { isReachable(node, t) } or
/** Intermediate node for following backward data flow. */
MkBackwardNode(DataFlow::LocalSourceNode node, TypeTracker t) { isReachable(node, t) } or
@@ -523,10 +475,30 @@ module API {
pragma[inline_late]
private DataFlow::Node getNodeFromExpr(Expr e) { result.asExpr().getExpr() = e }
+ private import frameworks.data.ModelsAsData
+
+ cached
+ predicate namespace(string name, Node node) {
+ exists(DataFlow::QualifiedTypeNameNode typeName |
+ typeName.getNamespace() = name and
+ node = MkNamespaceOfTypeNameNode(typeName)
+ )
+ or
+ exists(UsingStmt using |
+ using.getName().toLowerCase() = name and
+ node = MkUsingNode(using)
+ )
+ or
+ node = ModelOutput::getATypeNode(name)
+ }
+
+ cached
+ predicate topLevelMember(string name, Node node) { memberEdge(root(), name, node) }
+
cached
predicate toplevelCall(string name, Node node) {
exists(DataFlow::CallNode call |
- call.asExpr().getExpr().getEnclosingScope() instanceof TopLevel and
+ call.asExpr().getExpr().getEnclosingScope() instanceof TopLevelScriptBlock and
call.getName() = name and
node = MkMethodAccessNode(call)
)
@@ -544,26 +516,25 @@ module API {
cached
predicate memberEdge(Node pred, string name, Node succ) {
- exists(MemberExpr member | succ = getForwardStartNode(getNodeFromExpr(member)) |
- pred = getForwardEndNode(getALocalSourceStrict(getNodeFromExpr(member.getQualifier()))) and
- name = member.getMemberName()
+ exists(StringConstExpr read |
+ succ = getForwardStartNode(getNodeFromExpr(read)) and
+ pred = MkRoot() and
+ name = read.getValueString()
+ )
+ or
+ exists(DataFlow::QualifiedTypeNameNode typeName |
+ typeName.getName() = name and
+ pred = MkNamespaceOfTypeNameNode(typeName) and
+ succ = getForwardStartNode(typeName)
)
+ // or
+ // TODO: Handle getAMember when the predecessor is a MkUsingNode?
}
cached
predicate methodEdge(Node pred, string name, Node succ) {
exists(DataFlow::CallNode call | succ = MkMethodAccessNode(call) and name = call.getName() |
pred = getForwardEndNode(getALocalSourceStrict(call.getQualifier()))
- or
- exists(string qualifiedModule, ModuleManifest manifest, int n |
- pred = mod(qualifiedModule, n) and
- not exists(mod(qualifiedModule, n + 1)) and
- manifest.getModuleName() = qualifiedModule
- |
- manifest.getACmdLetToExport() = name
- or
- manifest.getAFunctionToExport() = name
- )
)
}
@@ -657,24 +628,10 @@ module API {
cached
predicate instanceEdge(Node pred, Node succ) {
- exists(string qualifiedType, int n |
- pred = MkModule(qualifiedType, n) and
- not exists(MkModule(qualifiedType, n + 1))
- |
- exists(DataFlow::TypeNameNode typeName |
- typeName.getTypeName() = qualifiedType and
- succ = getForwardStartNode(typeName)
- )
- or
- exists(DataFlow::ObjectCreationNode objCreation |
- objCreation.getConstructedTypeName() = qualifiedType and
- succ = getForwardStartNode(objCreation)
- )
- or
- exists(DataFlow::ParameterNode p |
- p.getParameter().getStaticType() = qualifiedType and
- succ = getForwardStartNode(p)
- )
+ // TODO: Also model parameters with a given type here
+ exists(DataFlow::ObjectCreationNode objCreation |
+ pred = getForwardEndNode(objCreation.getConstructedTypeNode()) and
+ succ = getForwardStartNode(objCreation)
)
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ArrayExpression.qll b/powershell/ql/lib/semmle/code/powershell/ArrayExpression.qll
deleted file mode 100644
index 4228b3f34396..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/ArrayExpression.qll
+++ /dev/null
@@ -1,26 +0,0 @@
-import powershell
-
-class ArrayExpr extends @array_expression, Expr {
- override SourceLocation getLocation() { array_expression_location(this, result) }
-
- StmtBlock getStmtBlock() { array_expression(this, result) }
-
- /**
- * Gets the i'th element of this `ArrayExpr`, if this can be determined statically.
- *
- * See `getStmtBlock` when the array elements are not known statically.
- */
- Expr getElement(int i) {
- result =
- unique( | | this.getStmtBlock().getAStmt()).(CmdExpr).getExpr().(ArrayLiteral).getElement(i)
- }
-
- /**
- * Gets an element of this `ArrayExpr`, if this can be determined statically.
- *
- * See `getStmtBlock` when the array elements are not known statically.
- */
- Expr getAnElement() { result = this.getElement(_) }
-
- override string toString() { result = "@(...)" }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Ast.qll b/powershell/ql/lib/semmle/code/powershell/Ast.qll
deleted file mode 100644
index a5c43472bc7d..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Ast.qll
+++ /dev/null
@@ -1,14 +0,0 @@
-import powershell
-private import semmle.code.powershell.controlflow.internal.Scope
-
-class Ast extends @ast {
- string toString() { none() }
-
- Ast getParent() { parent(this, result) }
-
- Location getLocation() { none() }
-
- Scope getEnclosingScope() { result = scopeOf(this) }
-
- final Function getEnclosingFunction() { this.getEnclosingScope() = result.getBody() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Call.qll b/powershell/ql/lib/semmle/code/powershell/Call.qll
deleted file mode 100644
index b5516344cc60..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Call.qll
+++ /dev/null
@@ -1,79 +0,0 @@
-import powershell
-private import semmle.code.powershell.dataflow.internal.DataFlowImplCommon
-private import semmle.code.powershell.dataflow.internal.DataFlowDispatch
-private import semmle.code.powershell.controlflow.CfgNodes
-
-abstract private class AbstractCall extends Ast {
- abstract Expr getCommand();
-
- abstract string getName();
-
- /** Gets the i'th argument to this call. */
- abstract Expr getArgument(int i);
-
- /** Gets the i'th positional argument to this call. */
- abstract Expr getPositionalArgument(int i);
-
- /** Holds if an argument with name `name` is provided to this call. */
- final predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
-
- /** Gets the argument to this call with the name `name`. */
- abstract Expr getNamedArgument(string name);
-
- /** Gets any argument to this call. */
- final Expr getAnArgument() { result = this.getArgument(_) }
-
- /** Gets the qualifier of this call, if any. */
- Expr getQualifier() { none() }
-
- /** Gets a possible runtime target of this call. */
- abstract Function getATarget();
-}
-
-/** A call to a command. For example, `Write-Host "Hello, world!"`. */
-class CmdCall extends AbstractCall instanceof Cmd {
- final override Expr getCommand() { result = Cmd.super.getCommand() }
-
- final override Expr getPositionalArgument(int i) { result = Cmd.super.getPositionalArgument(i) }
-
- final override string getName() { result = Cmd.super.getCommandName() }
-
- final override Expr getArgument(int i) { result = Cmd.super.getArgument(i) }
-
- final override Expr getNamedArgument(string name) { result = Cmd.super.getNamedArgument(name) }
-
- final override Function getATarget() {
- exists(DataFlowCall call | call.asCall().(StmtNodes::CmdCfgNode).getStmt() = this |
- result.getBody() = viableCallableLambda(call, _).asCfgScope()
- or
- result.getBody() = getTarget(call)
- )
- }
-}
-
-/** A call to a method on an object. For example, `$obj.ToString()`. */
-class MethodCall extends AbstractCall instanceof InvokeMemberExpr {
- final override Expr getCommand() { result = super.getMember() }
-
- final override Expr getPositionalArgument(int i) {
- result = InvokeMemberExpr.super.getArgument(i)
- }
-
- final override Expr getArgument(int i) { result = this.getPositionalArgument(i) }
-
- final override Expr getQualifier() { result = InvokeMemberExpr.super.getQualifier() }
-
- final override Expr getNamedArgument(string name) { none() }
-
- final override Function getATarget() {
- exists(DataFlowCall call | call.asCall().(ExprNodes::InvokeMemberCfgNode).getExpr() = this |
- result.getBody() = viableCallableLambda(call, _).asCfgScope()
- or
- result.getBody() = getTarget(call)
- )
- }
-
- final override string getName() { result = InvokeMemberExpr.super.getName() }
-}
-
-final class Call = AbstractCall;
diff --git a/powershell/ql/lib/semmle/code/powershell/CatchClause.qll b/powershell/ql/lib/semmle/code/powershell/CatchClause.qll
deleted file mode 100644
index 6d3bf4cb2971..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/CatchClause.qll
+++ /dev/null
@@ -1,39 +0,0 @@
-import powershell
-
-class CatchClause extends @catch_clause, Ast {
- override SourceLocation getLocation() { catch_clause_location(this, result) }
-
- override string toString() { result = "catch {...}" }
-
- StmtBlock getBody() { catch_clause(this, result, _) }
-
- TypeConstraint getCatchType(int i) { catch_clause_catch_type(this, i, result) }
-
- int getNumberOfCatchTypes() { result = count(this.getACatchType()) }
-
- TypeConstraint getACatchType() { result = this.getCatchType(_) }
-
- predicate isCatchAll() { not exists(this.getACatchType()) }
-
- TryStmt getTryStmt() { result.getACatchClause() = this }
-
- predicate isLast() {
- exists(TryStmt ts, int last |
- ts = this.getTryStmt() and
- last = max(int i | exists(ts.getCatchClause(i))) and
- this = ts.getCatchClause(last)
- )
- }
-}
-
-class GeneralCatchClause extends CatchClause {
- GeneralCatchClause() { this.isCatchAll() }
-
- override string toString() { result = "catch {...}" }
-}
-
-class SpecificCatchClause extends CatchClause {
- SpecificCatchClause() { not this.isCatchAll() }
-
- override string toString() { result = "catch[...] {...}" }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Command.qll b/powershell/ql/lib/semmle/code/powershell/Command.qll
deleted file mode 100644
index ffc63c91ff3f..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Command.qll
+++ /dev/null
@@ -1,114 +0,0 @@
-import powershell
-
-private predicate parseCommandName(Cmd cmd, string namespace, string name) {
- exists(string qualified | command(cmd, qualified, _, _, _) |
- namespace = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 1) and
- name = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 2)
- or
- // Not a qualified name
- not exists(qualified.indexOf("\\")) and
- namespace = "" and
- name = qualified
- )
-}
-
-/** A call to a command. */
-class Cmd extends @command, CmdBase {
- override string toString() {
- exists(string name | name = this.getQualifiedCommandName() |
- if name = "" then result = "call" else result = "call to " + name
- )
- or
- not exists(this.getQualifiedCommandName()) and
- result = "call"
- }
-
- override SourceLocation getLocation() { command_location(this, result) }
-
- /** Gets the name of the command without any qualifiers. */
- string getCommandName() { parseCommandName(this, _, result) }
-
- /** Holds if the command is qualified. */
- predicate isQualified() { parseCommandName(this, any(string s | s != ""), _) }
-
- /** Gets the namespace qualifier of this command, if any. */
- string getNamespaceQualifier() {
- result != "" and
- parseCommandName(this, result, _)
- or
- // Implicit import because it's in a module manifest
- parseCommandName(this, "", _) and
- exists(ModuleManifest manifest |
- manifest.getACmdLetToExport() = this.getCommandName() and
- result = manifest.getModuleName()
- )
- }
-
- /** Gets the (possibly qualified) name of this command. */
- string getQualifiedCommandName() { command(this, result, _, _, _) }
-
- int getKind() { command(this, _, result, _, _) }
-
- int getNumElements() { command(this, _, _, result, _) }
-
- int getNumRedirection() { command(this, _, _, _, result) }
-
- CmdElement getElement(int i) { command_command_element(this, i, result) }
-
- /** Gets the expression that determines the command to invoke. */
- Expr getCommand() { result = this.getElement(0) }
-
- /** Gets the name of this command, if this is statically known. */
- StringConstExpr getCmdName() { result = this.getElement(0) }
-
- /** Gets any argument to this command. */
- Expr getAnArgument() { result = this.getArgument(_) }
-
- /**
- * Gets the `i`th argument to this command.
- *
- * The argument may be named or positional.
- */
- Expr getArgument(int i) {
- result =
- rank[i + 1](CmdElement e, int j |
- e = this.getElement(j) and
- not e instanceof CmdParameter and
- j > 0 // 0'th element is the command name itself
- |
- e order by j
- )
- }
-
- /** Gets the `i`th positional argument to this command. */
- Expr getPositionalArgument(int i) {
- result =
- rank[i + 1](Argument e, int j |
- e = this.getArgument(j) and
- e instanceof PositionalArgument
- |
- e order by j
- )
- }
-
- /** Holds if this call has an argument named `name`. */
- predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
-
- /** Gets the named argument with the given name. */
- Expr getNamedArgument(string name) {
- exists(int i, CmdParameter p |
- this.getElement(i) = p and
- p.getName() = name and
- result = p.getArgument()
- )
- }
-
- Redirection getRedirection(int i) { command_redirection(this, i, result) }
-
- Redirection getARedirection() { result = this.getRedirection(_) }
-}
-
-/** A call to operator `&`. */
-class CallOperator extends Cmd {
- CallOperator() { this.getKind() = 28 }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/CommandParameter.qll b/powershell/ql/lib/semmle/code/powershell/CommandParameter.qll
deleted file mode 100644
index e1bb400b87b6..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/CommandParameter.qll
+++ /dev/null
@@ -1,23 +0,0 @@
-import powershell
-
-class CmdParameter extends @command_parameter, CmdElement {
- override SourceLocation getLocation() { command_parameter_location(this, result) }
-
- string getName() { command_parameter(this, result) }
-
- Expr getArgument() {
- // When an argumnt is of the form -Name:$var
- command_parameter_argument(this, result)
- or
- // When an argument is of the form -Name $var
- exists(int i, Cmd cmd |
- cmd = this.getCmd() and
- cmd.getElement(i) = this and
- result = cmd.getElement(i + 1)
- )
- }
-
- Cmd getCmd() { result.getElement(_) = this }
-
- override string toString() { command_parameter(this, result) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/ConvertExpr.qll b/powershell/ql/lib/semmle/code/powershell/ConvertExpr.qll
deleted file mode 100644
index e010804adb56..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/ConvertExpr.qll
+++ /dev/null
@@ -1,13 +0,0 @@
-import powershell
-
-class ConvertExpr extends @convert_expression, Expr {
- override string toString() { result = "[...]..." }
-
- override SourceLocation getLocation() { convert_expression_location(this, result) }
-
- Expr getBase() { convert_expression(this, _, result, _, _) }
-
- TypeConstraint getType() { convert_expression(this, _, _, result, _) }
-
- AttributeBase getAttribute() { convert_expression(this, result, _, _, _) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/DynamicStmt.qll b/powershell/ql/lib/semmle/code/powershell/DynamicStmt.qll
deleted file mode 100644
index 49c647af51d5..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/DynamicStmt.qll
+++ /dev/null
@@ -1,11 +0,0 @@
-import powershell
-
-class DynamicStmt extends @dynamic_keyword_statement, Stmt {
- override SourceLocation getLocation() { dynamic_keyword_statement_location(this, result) }
-
- override string toString() { result = "&..." }
-
- CmdElement getCmd(int i) { dynamic_keyword_statement_command_elements(this, i, result) }
-
- CmdElement getACmd() { result = this.getCmd(_) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Expression.qll b/powershell/ql/lib/semmle/code/powershell/Expression.qll
deleted file mode 100644
index 909c971f6e68..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Expression.qll
+++ /dev/null
@@ -1,11 +0,0 @@
-import powershell
-
-/**
- * An expression.
- *
- * This is the topmost class in the hierachy of all expression in PowerShell.
- */
-class Expr extends @expression, CmdElement {
- /** Gets the constant value of this expression, if this is known. */
- final ConstantValue getValue() { result.getAnExpr() = this }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Function.qll b/powershell/ql/lib/semmle/code/powershell/Function.qll
deleted file mode 100644
index f3b1cea97bdc..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Function.qll
+++ /dev/null
@@ -1,127 +0,0 @@
-import powershell
-import semmle.code.powershell.controlflow.BasicBlocks
-
-abstract private class AbstractFunction extends Ast {
- /** Gets the name of this function. */
- abstract string getName();
-
- /** Holds if this function has name `name`. */
- final predicate hasName(string name) { this.getName() = name }
-
- /** Gets the body of this function. */
- abstract ScriptBlock getBody();
-
- /**
- * Gets the i'th function parameter, if any.
- *
- * Note that this predicate only returns _function_ parameters.
- * To also get _block_ parameters use the `getParameter` predicate.
- */
- abstract Parameter getFunctionParameter(int i);
-
- /** Gets the declaring type of this function, if any. */
- abstract Type getDeclaringType();
-
- /**
- * Gets any function parameter of this function.
- *
- * Note that this only gets _function_ paramters. To get any parameter
- * use the `getAParameter` predicate.
- */
- final Parameter getAFunctionParameter() { result = this.getFunctionParameter(_) }
-
- /** Gets the number of function parameters. */
- final int getNumberOfFunctionParameters() { result = count(this.getAFunctionParameter()) }
-
- /**
- * Gets the number of parameters (both function and block).
- * Note: This excludes the `this` parameter.
- */
- final int getNumberOfParameters() { result = count(this.getAParameter()) }
-
- /**
- * Gets the i'th parameter of this function, if any.
- *
- * This does not include the `this` parameter.
- *
- * The implicit underscore parameter (if any) is included at index `-1`.
- */
- final Parameter getParameter(int i) {
- result.getFunction() = this and
- result.getIndex() = i
- }
-
- final Parameter getParameterExcludingPiplines(int i) {
- result = this.getFunctionParameter(i)
- or
- result = this.getBody().getParamBlock().getParameterExcludingPiplines(i)
- }
-
- final Parameter getThisParameter() {
- result.isThis() and
- result.getFunction() = this
- }
-
- /** Gets any parameter of this function. */
- final Parameter getAParameter() { result = this.getParameter(_) }
-
- /** Gets the entry point of this function in the control-flow graph. */
- EntryBasicBlock getEntryBasicBlock() { result.getScope() = this.getBody() }
-}
-
-final class Function = AbstractFunction;
-
-/**
- * A function definition.
- */
-private class FunctionBase extends @function_definition, Stmt, AbstractFunction {
- override string toString() { result = this.getName() }
-
- override SourceLocation getLocation() { function_definition_location(this, result) }
-
- override string getName() { function_definition(this, _, result, _, _) }
-
- override ScriptBlock getBody() { function_definition(this, result, _, _, _) }
-
- predicate isFilter() { function_definition(this, _, _, true, _) }
-
- predicate isWorkflow() { function_definition(this, _, _, _, true) }
-
- override Parameter getFunctionParameter(int i) { result.isFunctionParameter(this, i) }
-
- override Type getDeclaringType() { none() }
-}
-
-private predicate isMethod(Member m, ScriptBlock body) {
- function_member(m, body, _, _, _, _, _, _, _)
-}
-
-/**
- * A method definition. That is, a function defined inside a class definition.
- */
-class Method extends FunctionBase {
- Method() { isMethod(_, super.getBody()) }
-
- /** Gets the member corresponding to this function definition. */
- Member getMember() { isMethod(result, super.getBody()) }
-
- /** Holds if this method is a constructor. */
- predicate isConstructor() { function_member(this.getMember(), _, true, _, _, _, _, _, _) }
-
- final override Type getDeclaringType() { result = this.getMember().getDeclaringType() }
-}
-
-/** A constructor definition. */
-class Constructor extends Method {
- Constructor() { this.isConstructor() }
-}
-
-class TopLevel extends AbstractFunction instanceof TopLevelScriptBlock {
- final override string getName() { result = "toplevel" }
-
- final override ScriptBlock getBody() { result = this }
-
- final override Parameter getFunctionParameter(int i) { none() }
-
- final override Type getDeclaringType() { none() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/HashTable.qll b/powershell/ql/lib/semmle/code/powershell/HashTable.qll
deleted file mode 100644
index 5bd825a18f49..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/HashTable.qll
+++ /dev/null
@@ -1,21 +0,0 @@
-import powershell
-
-class HashTableExpr extends @hash_table, Expr {
- final override Location getLocation() { hash_table_location(this, result) }
-
- final override string toString() { result = "${...}" }
-
- Stmt getElement(Expr key) { hash_table_key_value_pairs(this, _, key, result) } // TODO: Change @ast to @expr in db scheme
-
- Stmt getElementFromConstant(string key) {
- result = this.getElement(any(StringConstExpr sc | sc.getValue().getValue() = key))
- }
-
- predicate hasKey(Expr key) { exists(this.getElement(key)) }
-
- Stmt getAnElement() { result = this.getElement(_) }
-
- predicate hasEntry(int index, Expr key, Stmt value) {
- hash_table_key_value_pairs(this, index, key, value)
- }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/IndexExpr.qll b/powershell/ql/lib/semmle/code/powershell/IndexExpr.qll
deleted file mode 100644
index cd31bb36b996..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/IndexExpr.qll
+++ /dev/null
@@ -1,30 +0,0 @@
-import powershell
-private import internal.ExplicitWrite::Private
-
-class IndexExpr extends @index_expression, Expr {
- override string toString() { result = "...[...]" }
-
- override SourceLocation getLocation() { index_expression_location(this, result) }
-
- Expr getIndex() { index_expression(this, result, _, _) } // TODO: Change @ast to @expr in the dbscheme
-
- Expr getBase() { index_expression(this, _, result, _) } // TODO: Change @ast to @expr in the dbscheme
-
- predicate isNullConditional() { index_expression(this, _, _, true) }
-}
-
-private predicate isImplicitIndexWrite(Expr e) { none() }
-
-/** An index expression that is being written to. */
-class IndexExprWrite extends IndexExpr {
- IndexExprWrite() { isExplicitWrite(this, _) or isImplicitIndexWrite(this) }
-
- predicate isExplicit(AssignStmt assign) { isExplicitWrite(this, assign) }
-
- predicate isImplicit() { isImplicitIndexWrite(this) }
-}
-
-/** An index expression that is being read from. */
-class IndexExprRead extends IndexExpr {
- IndexExprRead() { not this instanceof IndexExprWrite }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll b/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll
deleted file mode 100644
index c11d542cb228..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll
+++ /dev/null
@@ -1,49 +0,0 @@
-import powershell
-
-class InvokeMemberExpr extends @invoke_member_expression, MemberExprBase {
- override SourceLocation getLocation() { invoke_member_expression_location(this, result) }
-
- Expr getQualifier() { invoke_member_expression(this, result, _) }
-
- string getName() { result = this.getMember().(StringConstExpr).getValue().getValue() }
-
- CmdElement getMember() { invoke_member_expression(this, _, result) }
-
- string getMemberName() { result = this.getMember().(StringConstExpr).getValue().getValue() }
-
- Expr getArgument(int i) { invoke_member_expression_argument(this, i, result) }
-
- Expr getAnArgument() { invoke_member_expression_argument(this, _, result) }
-
- override string toString() { result = "call to " + this.getName() }
-
- override predicate isStatic() { this.getQualifier() instanceof TypeNameExpr }
-}
-
-/**
- * A call to a constructor. For example:
- *
- * ```powershell
- * [System.IO.FileInfo]::new("C:\\file.txt")
- * ```
- */
-class ConstructorCall extends InvokeMemberExpr {
- TypeNameExpr typename;
-
- ConstructorCall() {
- this.isStatic() and typename = this.getQualifier() and this.getName() = "new"
- }
-
- /**
- * Gets the type being constructed by this constructor call.
- *
- * Note that the type may not exist in the database.
- *
- * Use `getConstructedTypeName` to get the name of the type (which will
- * always exist in the database).
- */
- Type getConstructedType() { result = typename.getType() }
-
- /** Gets the name of the type being constructed by this constructor call. */
- string getConstructedTypeName() { result = typename.getName() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Member.qll b/powershell/ql/lib/semmle/code/powershell/Member.qll
deleted file mode 100644
index 15bdcad8d7e4..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Member.qll
+++ /dev/null
@@ -1,17 +0,0 @@
-import powershell
-
-class Member extends @member, Ast {
- Type getDeclaringType() { result.getAMember() = this }
-
- string getName() { none() }
-
- override string toString() { result = this.getName() }
-
- predicate isHidden() { none() }
-
- predicate isPrivate() { none() }
-
- predicate isPublic() { none() }
-
- predicate isStatic() { none() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/ModuleManifest.qll b/powershell/ql/lib/semmle/code/powershell/ModuleManifest.qll
deleted file mode 100644
index 691216d391d3..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/ModuleManifest.qll
+++ /dev/null
@@ -1,44 +0,0 @@
-import powershell
-
-class ModuleManifestFile extends File {
- ModuleManifestFile() { this.getExtension() = "psd1" }
-}
-
-private Expr getEntry(HashTableExpr ht, string key) {
- result = ht.getElementFromConstant(key).(CmdExpr).getExpr() and
- not result instanceof ArrayLiteral
-}
-
-private Expr getAnEntry(HashTableExpr ht, string key) {
- exists(Expr e | e = ht.getElementFromConstant(key).(CmdExpr).getExpr() |
- not e instanceof ArrayLiteral and result = e
- or
- result = e.(ArrayLiteral).getAnElement()
- )
-}
-
-class ModuleManifest extends HashTableExpr {
- string moduleVersion;
-
- ModuleManifest() {
- // The hash table is in a .psd1 file
- this.getLocation().getFile() instanceof ModuleManifestFile and
- // It's at the top level of the file
- this.getParent().(CmdExpr).getParent().(NamedBlock).getParent() instanceof TopLevel and
- // It has a `ModuleVersion` entry. The only required field is ModuleVersion.
- // https://learn.microsoft.com/en-us/powershell/scripting/developer/module/how-to-write-a-powershell-module-manifest?view=powershell-7.4#to-create-and-use-a-module-manifest
- moduleVersion = getEntry(this, "ModuleVersion").getValue().asString()
- }
-
- string getModuleVersion() { result = moduleVersion }
-
- string getModuleName() {
- result + ".psd1" = this.getLocation().getFile().getBaseName()
- }
-
- string getAFunctionToExport() {
- result = getAnEntry(this, "FunctionsToExport").getValue().asString()
- }
-
- string getACmdLetToExport() { result = getAnEntry(this, "CmdletsToExport").getValue().asString() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/ObjectCreation.qll b/powershell/ql/lib/semmle/code/powershell/ObjectCreation.qll
deleted file mode 100644
index ea3ed4f2239f..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/ObjectCreation.qll
+++ /dev/null
@@ -1,55 +0,0 @@
-import powershell
-
-abstract private class AbstractObjectCreation extends Call {
- /**
- * The type of the object being constructed.
- * Note that the type may not exist in the database.
- *
- * Use `getConstructedTypeName` to get the name of the type (which will
- * always exist in the database).
- */
- abstract Type getConstructedType();
-
- /** The name of the type of the object being constructed. */
- abstract string getConstructedTypeName();
-}
-
-/**
- * An object creation from a call to a constructor. For example:
- * ```powershell
- * [System.IO.FileInfo]::new("C:\\file.txt")
- * ```
- */
-class NewObjectCreation extends AbstractObjectCreation instanceof ConstructorCall {
- final override Type getConstructedType() { result = ConstructorCall.super.getConstructedType() }
-
- final override string getConstructedTypeName() {
- result = ConstructorCall.super.getConstructedTypeName()
- }
-}
-
-/**
- * An object creation from a call to `New-Object`. For example:
- * ```powershell
- * New-Object -TypeName System.IO.FileInfo -ArgumentList "C:\\file.txt"
- * ```
- */
-class DotNetObjectCreation extends AbstractObjectCreation instanceof Cmd {
- DotNetObjectCreation() { this.getCommandName() = "New-Object" }
-
- final override Type getConstructedType() { none() }
-
- final override string getConstructedTypeName() {
- // Either it's the named argument `TypeName`
- result = Cmd.super.getNamedArgument("TypeName").(StringConstExpr).getValue().getValue()
- or
- // Or it's the first positional argument if that's the named argument
- not Cmd.super.hasNamedArgument("TypeName") and
- exists(StringConstExpr arg | arg = Cmd.super.getPositionalArgument(0) |
- result = arg.getValue().getValue() and
- not arg = Cmd.super.getNamedArgument(["ArgumentList", "Property"])
- )
- }
-}
-
-final class ObjectCreation = AbstractObjectCreation;
diff --git a/powershell/ql/lib/semmle/code/powershell/ParamBlock.qll b/powershell/ql/lib/semmle/code/powershell/ParamBlock.qll
deleted file mode 100644
index 7c35517319b8..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/ParamBlock.qll
+++ /dev/null
@@ -1,21 +0,0 @@
-import powershell
-
-class ParamBlock extends @param_block, Ast {
- override string toString() { result = "param(...)" }
-
- override SourceLocation getLocation() { param_block_location(this, result) }
-
- int getNumAttributes() { param_block(this, result, _) }
-
- int getNumParameters() { param_block(this, _, result) }
-
- Attribute getAttribute(int i) { param_block_attribute(this, i, result) }
-
- Attribute getAnAttribute() { result = this.getAttribute(_) }
-
- Parameter getParameter(int i) { result.hasParameterBlock(this, i) }
-
- Parameter getParameterExcludingPiplines(int i) { result.hasParameterBlockExcludingPipelines(this, i) }
-
- Parameter getAParameter() { result = this.getParameter(_) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Redirection.qll b/powershell/ql/lib/semmle/code/powershell/Redirection.qll
deleted file mode 100644
index f2a31116f615..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Redirection.qll
+++ /dev/null
@@ -1,3 +0,0 @@
-import powershell
-
-class Redirection extends @redirection, Ast { }
diff --git a/powershell/ql/lib/semmle/code/powershell/SplitExpr.qll b/powershell/ql/lib/semmle/code/powershell/SplitExpr.qll
deleted file mode 100644
index f7c5df7fde99..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/SplitExpr.qll
+++ /dev/null
@@ -1,28 +0,0 @@
-import powershell
-
-abstract private class AbstractSplitExpr extends Expr {
- abstract Expr getExpr();
-
- /** ..., if any. */
- Expr getSeparator() { none() }
-}
-
-final class SplitExpr = AbstractSplitExpr;
-
-class UnarySplitExpr extends AbstractSplitExpr, UnaryExpr {
- UnarySplitExpr() { this.getKind() = 75 }
-
- final override string toString() { result = "-split ..." }
-
- final override Expr getExpr() { result = this.getOperand() }
-}
-
-class BinarySplitExpr extends AbstractSplitExpr, BinaryExpr {
- BinarySplitExpr() { this.getKind() = 75 }
-
- final override string toString() { result = "... -split ..." }
-
- final override Expr getExpr() { result = this.getLeft() }
-
- final override Expr getSeparator() { result = this.getRight() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/TrapStatement.qll b/powershell/ql/lib/semmle/code/powershell/TrapStatement.qll
deleted file mode 100644
index 34da4d2e111e..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/TrapStatement.qll
+++ /dev/null
@@ -1,7 +0,0 @@
-import powershell
-
-class TrapStmt extends @trap_statement, Stmt {
- override SourceLocation getLocation() { trap_statement_location(this, result) }
-
- override string toString() { result = "TrapStatement at: " + this.getLocation().toString() }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/UsingExpression.qll b/powershell/ql/lib/semmle/code/powershell/UsingExpression.qll
deleted file mode 100644
index 6c2e4eff62f0..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/UsingExpression.qll
+++ /dev/null
@@ -1,7 +0,0 @@
-import powershell
-
-class UsingExpr extends @using_expression, Expr {
- override string toString() { result = "$using..." }
-
- override SourceLocation getLocation() { using_expression_location(this, result) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/Variable.qll b/powershell/ql/lib/semmle/code/powershell/Variable.qll
deleted file mode 100644
index f5cb7259e0e5..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/Variable.qll
+++ /dev/null
@@ -1,406 +0,0 @@
-private import powershell
-private import semmle.code.powershell.controlflow.internal.Scope
-private import internal.Parameter::Private as Internal
-
-private predicate isFunctionParameterImpl(Internal::Parameter p, Function f, int i) {
- function_definition_parameter(f, i, p)
-}
-
-private predicate hasParameterBlockImpl(Internal::Parameter p, ParamBlock block, int i) {
- param_block_parameter(block, i, p)
-}
-
-private predicate hasParameterBlockExcludingPipelinesImpl(
- Internal::Parameter p, ParamBlock block, int i
-) {
- p =
- rank[i + 1](Internal::Parameter cand, int j |
- hasParameterBlockImpl(cand, block, j) and
- not cand.getAnAttribute().(Attribute).getANamedArgument() instanceof
- ValueFromPipelineAttribute and
- not cand.getAnAttribute().(Attribute).getANamedArgument() instanceof
- ValueFromPipelineByPropertyName
- |
- cand order by j
- )
-}
-
-/**
- * Gets the enclosing scope of `p`.
- *
- * For a function parameter, this is the function body. For a parameter from a
- * parameter block, this is the enclosing scope of the parameter block.
- *
- * In both of the above cases, the enclosing scope is the function body.
- */
-private Scope getEnclosingScopeImpl(Internal::Parameter p) {
- exists(Function f |
- isFunctionParameterImpl(p, f, _) and
- result = f.getBody()
- )
- or
- exists(ParamBlock b |
- hasParameterBlockImpl(p, b, _) and
- result = b.getEnclosingScope()
- )
-}
-
-bindingset[scope]
-pragma[inline_late]
-private predicate isParameterImpl(string name, Scope scope) {
- exists(Internal::Parameter p | p.getName() = name and getEnclosingScopeImpl(p) = scope)
- or
- name = "_"
-}
-
-private predicate isThisParameter(Scope scope, Type t) {
- t = scope.getEnclosingFunction().getDeclaringType()
-}
-
-private newtype TParameterImpl =
- TInternalParameter(Internal::Parameter p) or
- TUnderscore(Scope scope) {
- exists(VarAccess va | va.getUserPath() = ["_", "PSItem"] and scope = va.getEnclosingScope())
- } or
- TThisParameter(Scope scope) { isThisParameter(scope, _) }
-
-private class ParameterImpl extends TParameterImpl {
- abstract Location getLocation();
-
- string toString() { result = this.getName() }
-
- abstract string getName();
-
- abstract Scope getEnclosingScope();
-
- predicate hasParameterBlock(ParamBlock block, int i) { none() }
-
- predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) { none() }
-
- predicate isFunctionParameter(Function f, int i) { none() }
-
- Expr getDefaultValue() { none() }
-
- abstract Attribute getAnAttribute();
-
- VarAccess getAnAccess() {
- // TODO: This won't join order nicely.
- result.getUserPath() = this.getName() and
- result.getEnclosingScope() = this.getEnclosingScope()
- }
-
- abstract predicate isPipeline();
-
- abstract predicate isPipelineByPropertyName();
-
- /**
- * Gets the static type of this parameter.
- * The type of this parameter at runtime may be a subtype of this static
- * type.
- */
- abstract string getStaticType();
-}
-
-private class InternalParameter extends ParameterImpl, TInternalParameter {
- Internal::Parameter p;
-
- InternalParameter() { this = TInternalParameter(p) }
-
- override Location getLocation() { result = p.getLocation() }
-
- override string getName() { result = p.getName() }
-
- final override Scope getEnclosingScope() { result = getEnclosingScopeImpl(p) }
-
- override predicate hasParameterBlock(ParamBlock block, int i) {
- hasParameterBlockImpl(p, block, i)
- }
-
- override predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) {
- hasParameterBlockExcludingPipelinesImpl(p, block, i)
- }
-
- override predicate isFunctionParameter(Function f, int i) { isFunctionParameterImpl(p, f, i) }
-
- override Expr getDefaultValue() { result = p.getDefaultValue() }
-
- override Attribute getAnAttribute() { result = p.getAnAttribute() }
-
- override predicate isPipeline() {
- this.getAnAttribute().getANamedArgument() instanceof ValueFromPipelineAttribute
- }
-
- override predicate isPipelineByPropertyName() {
- this.getAnAttribute().getANamedArgument() instanceof ValueFromPipelineByPropertyName
- }
-
- final override string getStaticType() { result = p.getStaticType() }
-}
-
-/**
- * The variable that represents an element in the pipeline.
- *
- * This is either the variable `$_` or the variable `$PSItem`.
- */
-private class Underscore extends ParameterImpl, TUnderscore {
- Scope scope;
-
- Underscore() { this = TUnderscore(scope) }
-
- override Location getLocation() {
- // The location is the first access (ordered by location) to the variable in the scope
- exists(VarAccess va |
- va =
- min(VarAccess cand, Location location |
- cand = this.getAnAccess() and location = cand.getLocation()
- |
- cand order by location.getStartLine(), location.getStartColumn()
- ) and
- result = va.getLocation()
- )
- }
-
- override string getName() { result = "_" }
-
- final override Scope getEnclosingScope() { result = scope }
-
- final override Attribute getAnAttribute() { none() }
-
- final override predicate isPipeline() { any() }
-
- final override predicate isPipelineByPropertyName() { none() }
-
- final override predicate isFunctionParameter(Function f, int i) { f.getBody() = scope and i = -1 }
-
- final override string getStaticType() { none() }
-}
-
-private class ThisParameter extends ParameterImpl, TThisParameter {
- Scope scope;
-
- ThisParameter() { this = TThisParameter(scope) }
-
- override Location getLocation() { result = scope.getLocation() }
-
- override string getName() { result = "this" }
-
- final override Scope getEnclosingScope() { result = scope }
-
- final override Attribute getAnAttribute() { none() }
-
- final override predicate isPipeline() { none() }
-
- final override predicate isPipelineByPropertyName() { none() }
-
- final override string getStaticType() {
- exists(Type t |
- isThisParameter(scope, t) and
- result = t.getName()
- )
- }
-}
-
-private predicate isPipelineIteratorVariable(ParameterImpl p, ProcessBlock pb) {
- p.isPipeline() and
- pb.getEnclosingScope() = p.getEnclosingScope()
-}
-
-private predicate isPipelineByPropertyNameIteratorVariable(ParameterImpl p, ProcessBlock pb) {
- p.isPipelineByPropertyName() and
- pb.getEnclosingScope() = p.getEnclosingScope()
-}
-
-private newtype TVariable =
- TLocalVariable(string name, Scope scope) {
- not isParameterImpl(name, scope) and
- not name = "this" and // This is modeled as a parameter
- exists(VarAccess va | va.getUserPath() = name and scope = va.getEnclosingScope())
- } or
- TParameter(ParameterImpl p) or
- TPipelineIteratorVariable(ProcessBlock pb) { isPipelineIteratorVariable(_, pb) } or
- TPipelineByPropertyNameIteratorVariable(ParameterImpl p) {
- isPipelineByPropertyNameIteratorVariable(p, _)
- }
-
-private class AbstractVariable extends TVariable {
- abstract Location getLocation();
-
- string toString() { result = this.getName() }
-
- abstract string getName();
-
- final predicate hasName(string s) { this.getName() = s }
-
- abstract Scope getDeclaringScope();
-
- VarAccess getAnAccess() {
- exists(string s |
- s = concat(this.getAQlClass(), ", ") and
- // TODO: This won't join order nicely.
- result.getUserPath() = this.getName() and
- result.getEnclosingScope() = this.getDeclaringScope()
- )
- }
-}
-
-final class Variable = AbstractVariable;
-
-abstract class AbstractLocalScopeVariable extends AbstractVariable { }
-
-final class LocalScopeVariable = AbstractLocalScopeVariable;
-
-class LocalVariable extends AbstractLocalScopeVariable, TLocalVariable {
- string name;
- Scope scope;
-
- LocalVariable() { this = TLocalVariable(name, scope) }
-
- override Location getLocation() {
- // The location is the first access (ordered by location) to the variable in the scope
- exists(VarAccess va |
- va =
- min(VarAccess cand, Location location |
- cand = this.getAnAccess() and location = cand.getLocation()
- |
- cand order by location.getStartLine(), location.getStartColumn()
- ) and
- result = va.getLocation()
- )
- }
-
- override string getName() { result = name }
-
- final override Scope getDeclaringScope() { result = scope }
-}
-
-/**
- * A variable of the form `$Env:HOME`.
- */
-class EnvVariable extends Variable {
- string var;
-
- EnvVariable() { this.getName() = ["env:", "Env:"] + var }
-
- /**
- * Gets the part of the variable name that represens which environment
- * variable.
- */
- string getEnvironmentVariable() { result = var }
-}
-
-class Parameter extends AbstractLocalScopeVariable, TParameter {
- ParameterImpl p;
-
- Parameter() { this = TParameter(p) }
-
- override Location getLocation() { result = p.getLocation() }
-
- override string getName() { result = p.getName() }
-
- final predicate hasName(string name) { name = p.getName() }
-
- final override Scope getDeclaringScope() { result = p.getEnclosingScope() }
-
- predicate hasParameterBlock(ParamBlock block, int i) { p.hasParameterBlock(block, i) }
-
- predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) {
- p.hasParameterBlockExcludingPipelines(block, i)
- }
-
- predicate isFunctionParameter(Function f, int i) { p.isFunctionParameter(f, i) }
-
- Expr getDefaultValue() { result = p.getDefaultValue() }
-
- predicate hasDefaultValue() { exists(this.getDefaultValue()) }
-
- /** Holds if this is the `this` parameter. */
- predicate isThis() { p instanceof ThisParameter }
-
- /**
- * Gets the index of this parameter, if any.
- *
- * The parameter may be in a parameter block or a function parameter.
- */
- int getIndex() { result = this.getFunctionIndex() or result = this.getBlockIndex() }
-
- int getIndexExcludingPipelines() {
- result = this.getFunctionIndex() or result = this.getBlockIndexExcludingPipelines()
- }
-
- /** Gets the index of this parameter in the parameter block, if any. */
- int getBlockIndex() { this.hasParameterBlock(_, result) }
-
- int getBlockIndexExcludingPipelines() { this.hasParameterBlockExcludingPipelines(_, result) }
-
- /** Gets the index of this parameter in the function, if any. */
- int getFunctionIndex() { this.isFunctionParameter(_, result) }
-
- Function getFunction() { result.getBody() = this.getDeclaringScope() }
-
- Attribute getAnAttribute() { result = p.getAnAttribute() }
-
- predicate isPipeline() { p.isPipeline() }
-
- predicate isPipelineByPropertyName() { p.isPipelineByPropertyName() }
-
- string getStaticType() { result = p.getStaticType() }
-}
-
-class PipelineParameter extends Parameter {
- PipelineParameter() { this.isPipeline() }
-
- PipelineIteratorVariable getIteratorVariable() {
- result.getProcessBlock().getEnclosingScope() = p.getEnclosingScope()
- }
-}
-
-class PipelineByPropertyNameParameter extends Parameter {
- PipelineByPropertyNameParameter() { this.isPipelineByPropertyName() }
-
- PipelineByPropertyNameIteratorVariable getIteratorVariable() { result.getParameter() = this }
-}
-
-/**
- * The variable that represents the value of a pipeline during a process block.
- *
- * That is, it is _not_ the `ValueFromPipeline` variable, but the value that is obtained by reading
- * from the pipeline.
- */
-class PipelineIteratorVariable extends AbstractLocalScopeVariable, TPipelineIteratorVariable {
- private ProcessBlock pb;
-
- PipelineIteratorVariable() { this = TPipelineIteratorVariable(pb) }
-
- override Location getLocation() { result = pb.getLocation() }
-
- override string getName() { result = "pipeline iterator for " + pb.toString() }
-
- final override Scope getDeclaringScope() { result = pb.getEnclosingScope() }
-
- ProcessBlock getProcessBlock() { result = pb }
-}
-
-/**
- * The variable that represents the value of a pipeline that picks out a
- * property specific property during a process block.
- *
- * That is, it is _not_ the `PipelineByPropertyName` variable, but the value that is obtained by reading
- * from the pipeline.
- */
-class PipelineByPropertyNameIteratorVariable extends AbstractLocalScopeVariable,
- TPipelineByPropertyNameIteratorVariable
-{
- private ParameterImpl p;
-
- PipelineByPropertyNameIteratorVariable() { this = TPipelineByPropertyNameIteratorVariable(p) }
-
- override Location getLocation() { result = p.getLocation() }
-
- override string getName() { result = "pipeline iterator for " + p.toString() }
-
- final override Scope getDeclaringScope() { result = p.getEnclosingScope() }
-
- Parameter getParameter() { result = TParameter(p) }
-
- ProcessBlock getProcessBlock() { isPipelineByPropertyNameIteratorVariable(p, result) }
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/Ast.qll b/powershell/ql/lib/semmle/code/powershell/ast/Ast.qll
new file mode 100644
index 000000000000..f32a9982b51f
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/Ast.qll
@@ -0,0 +1 @@
+import internal.Internal::Public
\ No newline at end of file
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayExpression.qll
new file mode 100644
index 000000000000..ae418c4d5117
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayExpression.qll
@@ -0,0 +1,37 @@
+private import AstImport
+
+class ArrayExpr extends Expr, TArrayExpr {
+ StmtBlock getStmtBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, arrayExprStmtBlock(), result)
+ or
+ not synthChild(r, arrayExprStmtBlock(), result) and
+ result = getResultAst(r.(Raw::ArrayExpr).getStmtBlock())
+ )
+ }
+
+ override string toString() { result = "@(...)" }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = arrayExprStmtBlock() and result = this.getStmtBlock()
+ }
+
+ /**
+ * Gets the i'th element of this `ArrayExpr`, if this can be determined statically.
+ *
+ * See `getStmtBlock` when the array elements are not known statically.
+ */
+ Expr getExpr(int i) {
+ result =
+ unique( | | this.getStmtBlock().getAStmt()).(ExprStmt).getExpr().(ArrayLiteral).getExpr(i)
+ }
+
+ /**
+ * Gets an element of this `ArrayExpr`, if this can be determined statically.
+ *
+ * See `getStmtBlock` when the array elements are not known statically.
+ */
+ Expr getAnExpr() { result = this.getExpr(_) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayLiteral.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayLiteral.qll
new file mode 100644
index 000000000000..21427948b8ec
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ArrayLiteral.qll
@@ -0,0 +1,25 @@
+private import AstImport
+
+class ArrayLiteral extends Expr, TArrayLiteral {
+ Expr getExpr(int index) {
+ exists(ChildIndex i, Raw::Ast r | i = arrayLiteralExpr(index) and r = getRawAst(this) |
+ synthChild(r, i, result)
+ or
+ not synthChild(r, i, _) and
+ result = getResultAst(r.(Raw::ArrayLiteral).getElement(index))
+ )
+ }
+
+ Expr getAnExpr() { result = this.getExpr(_) }
+
+ override string toString() { result = "...,..." }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = arrayLiteralExpr(index) and
+ result = this.getExpr(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AssignmentStatement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AssignmentStatement.qll
new file mode 100644
index 000000000000..6f4cb8d2fbfe
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AssignmentStatement.qll
@@ -0,0 +1,33 @@
+private import AstImport
+
+class AssignStmt extends Stmt, TAssignStmt {
+ Expr getRightHandSide() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, assignStmtRightHandSide(), result)
+ or
+ not synthChild(r, assignStmtRightHandSide(), _) and
+ result = getResultAst(r.(Raw::AssignStmt).getRightHandSide())
+ )
+ }
+
+ Expr getLeftHandSide() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, assignStmtLeftHandSide(), result)
+ or
+ not synthChild(r, assignStmtLeftHandSide(), _) and
+ result = getResultAst(r.(Raw::AssignStmt).getLeftHandSide())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = assignStmtLeftHandSide() and
+ result = this.getLeftHandSide()
+ or
+ i = assignStmtRightHandSide() and
+ result = this.getRightHandSide()
+ }
+
+ override string toString() { result = "...=..." }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Ast.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Ast.qll
new file mode 100644
index 000000000000..78d1d97876c8
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Ast.qll
@@ -0,0 +1,37 @@
+private import AstImport
+
+class Ast extends TAst {
+ string toString() { none() }
+
+ final Ast getParent() { result.getChild(_) = this }
+
+ Location getLocation() {
+ result = getRawAst(this).getLocation()
+ or
+ result = any(Synthesis s).getLocation(this)
+ }
+
+ Ast getChild(ChildIndex i) {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, i, result)
+ or
+ exists(string name |
+ i = RealVar(name) and
+ result = TVariableReal(r, name, _)
+ )
+ )
+ }
+
+ final Ast getAChild() { result = this.getChild(_) }
+
+ Scope getEnclosingScope() { result = scopeOf(this) } // TODO: Scope of synth?
+
+ Function getEnclosingFunction() {
+ exists(Scope scope | scope = scopeOf(this) |
+ result.getBody() = scope
+ or
+ not scope instanceof ScriptBlock and
+ result = scope.getEnclosingFunction()
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AstImport.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AstImport.qll
new file mode 100644
index 000000000000..88f3720c7962
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AstImport.qll
@@ -0,0 +1,5 @@
+import TAst
+import Raw.Raw as Raw
+import Internal::Private
+import Internal::Public
+import Synthesis
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Attribute.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Attribute.qll
new file mode 100644
index 000000000000..87d70a7f18c0
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Attribute.qll
@@ -0,0 +1,58 @@
+private import AstImport
+
+class Attribute extends AttributeBase, TAttribute {
+ string getName() { result = getRawAst(this).(Raw::Attribute).getName() }
+
+ NamedAttributeArgument getNamedArgument(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = attributeNamedArg(i) and r = getRawAst(this) |
+ synthChild(r, attributeNamedArg(i), result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::Attribute).getNamedArgument(i))
+ )
+ }
+
+ NamedAttributeArgument getANamedArgument() { result = this.getNamedArgument(_) }
+
+ int getNumberOfArguments() { result = count(this.getAPositionalArgument()) }
+
+ Expr getPositionalArgument(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = attributePosArg(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::Attribute).getPositionalArgument(i))
+ )
+ }
+
+ Expr getAPositionalArgument() { result = this.getPositionalArgument(_) }
+
+ int getNumberOfPositionalArguments() { result = count(this.getAPositionalArgument()) }
+
+ private string toStringSpecific() {
+ not exists(this.getAPositionalArgument()) and
+ result = unique( | | this.getANamedArgument()).getName()
+ or
+ not exists(this.getANamedArgument()) and
+ result = unique( | | this.getANamedArgument()).getName()
+ }
+
+ override string toString() {
+ result = this.toStringSpecific()
+ or
+ not exists(this.toStringSpecific()) and
+ result = this.getName()
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = attributeNamedArg(index) and
+ result = this.getNamedArgument(index)
+ or
+ i = attributePosArg(index) and
+ result = this.getPositionalArgument(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributeBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributeBase.qll
new file mode 100644
index 000000000000..dbb261664be0
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributeBase.qll
@@ -0,0 +1,3 @@
+private import AstImport
+
+class AttributeBase extends Ast, TAttributeBase { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExpr.qll
new file mode 100644
index 000000000000..cb8f2c7021bd
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExpr.qll
@@ -0,0 +1,32 @@
+private import AstImport
+
+class AttributedExpr extends AttributedExprBase, TAttributedExpr {
+ final override string toString() { result = "[...]" + this.getExpr().toString() }
+
+ final override Expr getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, attributedExprExpr(), result)
+ or
+ not synthChild(r, attributedExprExpr(), _) and
+ result = getResultAst(r.(Raw::AttributedExpr).getExpr())
+ )
+ }
+
+ final override Attribute getAttribute() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, attributedExprAttr(), result)
+ or
+ not synthChild(r, attributedExprAttr(), _) and
+ result = getResultAst(r.(Raw::AttributedExpr).getAttribute())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = attributedExprExpr() and result = this.getExpr()
+ or
+ i = attributedExprAttr() and
+ result = this.getAttribute()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExprBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExprBase.qll
new file mode 100644
index 000000000000..488e113577d6
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AttributedExprBase.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class AttributedExprBase extends Expr, TAttributedExprBase {
+ Expr getExpr() { none() }
+
+ AttributeBase getAttribute() { none() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/AutomaticVariable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/AutomaticVariable.qll
new file mode 100644
index 000000000000..4196280a638a
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/AutomaticVariable.qll
@@ -0,0 +1,11 @@
+private import AstImport
+
+class AutomaticVariable extends Expr, TAutomaticVariable {
+ final override string toString() { result = this.getName() }
+
+ string getName() { any(Synthesis s).automaticVariableName(this, result) }
+}
+
+class MyInvocation extends AutomaticVariable {
+ MyInvocation() { this.getName() = "myinvocation" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/BinaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/BinaryExpression.qll
similarity index 90%
rename from powershell/ql/lib/semmle/code/powershell/BinaryExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/BinaryExpression.qll
index 7e7d4011b7f9..f40eba8a30a2 100644
--- a/powershell/ql/lib/semmle/code/powershell/BinaryExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/BinaryExpression.qll
@@ -1,29 +1,38 @@
-import powershell
+private import AstImport
+
+class BinaryExpr extends Expr, TBinaryExpr {
+ /** INTERNAL: Do not use. */
+ int getKind() { result = getRawAst(this).(Raw::BinaryExpr).getKind() }
+
+ Expr getLeft() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, binaryExprLeft(), result)
+ or
+ not synthChild(r, binaryExprLeft(), _) and
+ result = getResultAst(r.(Raw::BinaryExpr).getLeft())
+ )
+ }
-class BinaryExpr extends @binary_expression, Expr {
- override SourceLocation getLocation() { binary_expression_location(this, result) }
+ Expr getRight() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, binaryExprRight(), result)
+ or
+ not synthChild(r, binaryExprRight(), _) and
+ result = getResultAst(r.(Raw::BinaryExpr).getRight())
+ )
+ }
- int getKind() { binary_expression(this, result, _, _) }
+ Expr getAnOperand() { result = this.getLeft() or result = this.getRight() }
- /** Gets an operand of this binary expression. */
- Expr getAnOperand() {
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = binaryExprLeft() and
result = this.getLeft()
or
+ i = binaryExprRight() and
result = this.getRight()
}
-
- /** Holds if this binary expression has the operands `e1` and `e2`. */
- predicate hasOperands(Expr e1, Expr e2) {
- e1 = this.getLeft() and
- e2 = this.getRight()
- or
- e1 = this.getRight() and
- e2 = this.getLeft()
- }
-
- Expr getLeft() { binary_expression(this, _, result, _) }
-
- Expr getRight() { binary_expression(this, _, _, result) }
}
abstract private class AbstractArithmeticExpr extends BinaryExpr { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/BoolLiteral.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/BoolLiteral.qll
new file mode 100644
index 000000000000..36fef4912da7
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/BoolLiteral.qll
@@ -0,0 +1,9 @@
+private import AstImport
+
+class BoolLiteral extends Literal, TBoolLiteral {
+ final override string toString() { result = this.getValue().toString() }
+
+ final override ConstantValue getValue() { result.asBoolean() = this.getBoolValue() }
+
+ boolean getBoolValue() { any(Synthesis s).booleanValue(this, result) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/BreakStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/BreakStmt.qll
new file mode 100644
index 000000000000..f04899c3e81a
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/BreakStmt.qll
@@ -0,0 +1,5 @@
+private import AstImport
+
+class BreakStmt extends GotoStmt, TBreakStmt {
+ override string toString() { result = "break" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/CallExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/CallExpr.qll
new file mode 100644
index 000000000000..96659f6cda24
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/CallExpr.qll
@@ -0,0 +1,54 @@
+private import AstImport
+
+class CallExpr extends Expr, TCallExpr {
+ /** Gets the i'th argument to this call. */
+ Expr getArgument(int i) { none() }
+
+ /** Gets the name that is used to select the callee. */
+ string getName() { none() }
+
+ /** Gets the i'th positional argument to this call. */
+ Expr getPositionalArgument(int i) { none() }
+
+ /**
+ * Gets the expression that represents the callee. That is, the expression
+ * that computes the target of the call.
+ */
+ Expr getCallee() { none() }
+
+ /** Holds if an argument with name `name` is provided to this call. */
+ final predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
+
+ /** Gets the argument to this call with the name `name`. */
+ Expr getNamedArgument(string name) { none() }
+
+ /** Gets any argument to this call. */
+ final Expr getAnArgument() { result = this.getArgument(_) }
+
+ /** Gets the qualifier of this call, if any. */
+ Expr getQualifier() { none() }
+
+ final override string toString() { result = "Call to " + this.getName() }
+
+ predicate isStatic() { none() }
+}
+
+class Argument extends Expr {
+ CallExpr call;
+
+ Argument() { this = call.getAnArgument() }
+
+ int getPosition() { this = call.getPositionalArgument(result) }
+
+ string getName() { this = call.getNamedArgument(result) }
+
+ CallExpr getCall() { result = call }
+}
+
+class Qualifier extends Expr {
+ CallExpr call;
+
+ Qualifier() { this = call.getQualifier() }
+
+ CallExpr getCall() { result = call }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/CatchClause.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/CatchClause.qll
new file mode 100644
index 000000000000..3504e0f055ba
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/CatchClause.qll
@@ -0,0 +1,62 @@
+private import AstImport
+
+class CatchClause extends Ast, TCatchClause {
+ StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, catchClauseBody(), result)
+ or
+ not synthChild(r, catchClauseBody(), _) and
+ result = getResultAst(r.(Raw::CatchClause).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = catchClauseBody() and result = this.getBody()
+ or
+ exists(int index |
+ i = catchClauseType(index) and
+ result = this.getCatchType(index)
+ )
+ }
+
+ override string toString() { result = "catch {...}" }
+
+ TryStmt getTryStmt() { result.getACatchClause() = this }
+
+ predicate isLast() {
+ exists(TryStmt ts, int last |
+ ts = this.getTryStmt() and
+ last = max(int i | exists(ts.getCatchClause(i))) and
+ this = ts.getCatchClause(last)
+ )
+ }
+
+ TypeConstraint getCatchType(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = catchClauseType(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::CatchClause).getCatchType(i))
+ )
+ }
+
+ int getNumberOfCatchTypes() { result = count(this.getACatchType()) }
+
+ TypeConstraint getACatchType() { result = this.getCatchType(_) }
+
+ predicate isCatchAll() { not exists(this.getACatchType()) }
+}
+
+class GeneralCatchClause extends CatchClause {
+ GeneralCatchClause() { this.isCatchAll() }
+
+ override string toString() { result = "catch {...}" }
+}
+
+class SpecificCatchClause extends CatchClause {
+ SpecificCatchClause() { not this.isCatchAll() }
+
+ override string toString() { result = "catch[...] {...}" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ChildIndex.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ChildIndex.qll
new file mode 100644
index 000000000000..01eefb967621
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ChildIndex.qll
@@ -0,0 +1,267 @@
+private import Raw.Raw as Raw
+private import Scopes
+private import TAst
+
+newtype ChildIndex =
+ RawChildIndex(Raw::ChildIndex index) or
+ ParamPipeline() or
+ ParamDefaultVal() or
+ ParamAttr(int i) { exists(any(Raw::Parameter p).getAttribute(i)) } or
+ FunctionBody() or
+ ScriptBlockAttr(int i) { exists(any(Raw::ParamBlock sb).getAttribute(i)) } or
+ FunParam(int i) {
+ exists(any(Raw::ParamBlock pb).getParameter(i))
+ or
+ exists(any(Raw::FunctionDefinitionStmt func).getParameter(i))
+ or
+ // Synth an extra parameter index for a pipeline parameter if none is provided
+ exists(Raw::ParamBlock pb |
+ not pb.getAParameter() instanceof Raw::PipelineParameter and
+ i = pb.getNumParameters()
+ )
+ } or
+ CmdArgument(int i) { exists(any(Raw::Cmd cmd).getArgument(i)) } or
+ ExprStmtExpr() or
+ MethodBody() or
+ ExprRedirection(int i) { exists(any(Raw::Cmd cmdExpr).getRedirection(i)) } or
+ FunDefFun() or
+ TypeDefType() or
+ TypeMember(int i) {
+ exists(any(Raw::TypeStmt typedef).getMember(i))
+ // or
+ // hasMemberInType(_, _, i, _)
+ } or
+ ThisVar() or
+ PipelineParamVar() or
+ // PipelineByPropertNameVar(Raw::PipelineByPropertyNameParameter p) or
+ PipelineIteratorVar() or
+ PipelineByPropertyNameIteratorVar(Raw::PipelineByPropertyNameParameter p) or
+ RealVar(string name) { name = variableNameInScope(_, _) }
+
+int synthPipelineParameterChildIndex(Raw::ScriptBlock sb) {
+ exists(Raw::ParamBlock pb |
+ pb = sb.getParamBlock() and
+ not pb.getAParameter() instanceof Raw::PipelineParameter and
+ result = pb.getNumParameters()
+ )
+}
+
+Raw::ChildIndex toRawChildIndex(ChildIndex i) { i = RawChildIndex(result) }
+
+ChildIndex arrayExprStmtBlock() { result = RawChildIndex(Raw::ArrayExprStmtBlock()) }
+
+ChildIndex arrayLiteralExpr(int i) { result = RawChildIndex(Raw::ArrayLiteralExpr(i)) }
+
+ChildIndex assignStmtLeftHandSide() { result = RawChildIndex(Raw::AssignStmtLeftHandSide()) }
+
+ChildIndex assignStmtRightHandSide() { result = RawChildIndex(Raw::AssignStmtRightHandSide()) }
+
+ChildIndex memberAttr(int i) { result = RawChildIndex(Raw::MemberAttr(i)) }
+
+ChildIndex memberTypeConstraint() { result = RawChildIndex(Raw::MemberTypeConstraint()) }
+
+ChildIndex attributeNamedArg(int i) { result = RawChildIndex(Raw::AttributeNamedArg(i)) }
+
+ChildIndex attributePosArg(int i) { result = RawChildIndex(Raw::AttributePosArg(i)) }
+
+ChildIndex attributedExprExpr() { result = RawChildIndex(Raw::AttributedExprExpr()) }
+
+ChildIndex attributedExprAttr() { result = RawChildIndex(Raw::AttributedExprAttr()) }
+
+ChildIndex binaryExprLeft() { result = RawChildIndex(Raw::BinaryExprLeft()) }
+
+ChildIndex binaryExprRight() { result = RawChildIndex(Raw::BinaryExprRight()) }
+
+ChildIndex catchClauseBody() { result = RawChildIndex(Raw::CatchClauseBody()) }
+
+ChildIndex catchClauseType(int i) { result = RawChildIndex(Raw::CatchClauseType(i)) }
+
+ChildIndex cmdCallee() { result = RawChildIndex(Raw::CmdCallee()) }
+
+ChildIndex cmdArgument(int i) { result = CmdArgument(i) }
+
+ChildIndex cmdRedirection(int i) { result = RawChildIndex(Raw::CmdRedirection(i)) }
+
+ChildIndex cmdElement_(int i) { result = RawChildIndex(Raw::CmdElement_(i)) }
+
+ChildIndex cmdExprExpr() { result = RawChildIndex(Raw::CmdExprExpr()) }
+
+ChildIndex configurationName() { result = RawChildIndex(Raw::ConfigurationName()) }
+
+ChildIndex configurationBody() { result = RawChildIndex(Raw::ConfigurationBody()) }
+
+ChildIndex convertExprExpr() { result = RawChildIndex(Raw::ConvertExprExpr()) }
+
+ChildIndex convertExprType() { result = RawChildIndex(Raw::ConvertExprType()) }
+
+ChildIndex convertExprAttr() { result = RawChildIndex(Raw::ConvertExprAttr()) }
+
+ChildIndex dataStmtBody() { result = RawChildIndex(Raw::DataStmtBody()) }
+
+ChildIndex dataStmtCmdAllowed(int i) { result = RawChildIndex(Raw::DataStmtCmdAllowed(i)) }
+
+ChildIndex doUntilStmtCond() { result = RawChildIndex(Raw::DoUntilStmtCond()) }
+
+ChildIndex doUntilStmtBody() { result = RawChildIndex(Raw::DoUntilStmtBody()) }
+
+ChildIndex doWhileStmtCond() { result = RawChildIndex(Raw::DoWhileStmtCond()) }
+
+ChildIndex doWhileStmtBody() { result = RawChildIndex(Raw::DoWhileStmtBody()) }
+
+ChildIndex dynamicStmtName() { result = RawChildIndex(Raw::DynamicStmtName()) }
+
+ChildIndex dynamicStmtBody() { result = RawChildIndex(Raw::DynamicStmtBody()) }
+
+ChildIndex exprStmtExpr() { result = ExprStmtExpr() }
+
+ChildIndex exprRedirection(int i) { result = ExprRedirection(i) }
+
+ChildIndex exitStmtPipeline() { result = RawChildIndex(Raw::ExitStmtPipeline()) }
+
+ChildIndex expandableStringExprExpr(int i) {
+ result = RawChildIndex(Raw::ExpandableStringExprExpr(i))
+}
+
+ChildIndex forEachStmtVar() { result = RawChildIndex(Raw::ForEachStmtVar()) }
+
+ChildIndex forEachStmtIter() { result = RawChildIndex(Raw::ForEachStmtIter()) }
+
+ChildIndex forEachStmtBody() { result = RawChildIndex(Raw::ForEachStmtBody()) }
+
+ChildIndex forStmtInit() { result = RawChildIndex(Raw::ForStmtInit()) }
+
+ChildIndex forStmtCond() { result = RawChildIndex(Raw::ForStmtCond()) }
+
+ChildIndex forStmtIter() { result = RawChildIndex(Raw::ForStmtIter()) }
+
+ChildIndex forStmtBody() { result = RawChildIndex(Raw::ForStmtBody()) }
+
+ChildIndex functionBody() { result = FunctionBody() }
+
+ChildIndex funDefStmtBody() { result = RawChildIndex(Raw::FunDefStmtBody()) }
+
+ChildIndex funDefStmtParam(int i) { result = RawChildIndex(Raw::FunDefStmtParam(i)) }
+
+ChildIndex funDefFun() { result = FunDefFun() }
+
+ChildIndex typeDefType() { result = TypeDefType() }
+
+ChildIndex typeMember(int i) { result = TypeMember(i) }
+
+ChildIndex gotoStmtLabel() { result = RawChildIndex(Raw::GotoStmtLabel()) }
+
+ChildIndex hashTableExprKey(int i) { result = RawChildIndex(Raw::HashTableExprKey(i)) }
+
+ChildIndex hashTableExprStmt(int i) { result = RawChildIndex(Raw::HashTableExprStmt(i)) }
+
+ChildIndex ifStmtElse() { result = RawChildIndex(Raw::IfStmtElse()) }
+
+ChildIndex ifStmtCond(int i) { result = RawChildIndex(Raw::IfStmtCond(i)) }
+
+ChildIndex ifStmtThen(int i) { result = RawChildIndex(Raw::IfStmtThen(i)) }
+
+ChildIndex indexExprIndex() { result = RawChildIndex(Raw::IndexExprIndex()) }
+
+ChildIndex indexExprBase() { result = RawChildIndex(Raw::IndexExprBase()) }
+
+ChildIndex invokeMemberExprQual() { result = RawChildIndex(Raw::InvokeMemberExprQual()) }
+
+ChildIndex invokeMemberExprCallee() { result = RawChildIndex(Raw::InvokeMemberExprCallee()) }
+
+ChildIndex invokeMemberExprArg(int i) { result = RawChildIndex(Raw::InvokeMemberExprArg(i)) }
+
+ChildIndex memberExprQual() { result = RawChildIndex(Raw::MemberExprQual()) }
+
+ChildIndex memberExprMember() { result = RawChildIndex(Raw::MemberExprMember()) }
+
+ChildIndex methodBody() { result = MethodBody() }
+
+ChildIndex namedAttributeArgVal() { result = RawChildIndex(Raw::NamedAttributeArgVal()) }
+
+ChildIndex namedBlockStmt(int i) { result = RawChildIndex(Raw::NamedBlockStmt(i)) }
+
+ChildIndex namedBlockTrap(int i) { result = RawChildIndex(Raw::NamedBlockTrap(i)) }
+
+ChildIndex paramBlockAttr(int i) { result = RawChildIndex(Raw::ParamBlockAttr(i)) }
+
+ChildIndex paramBlockParam(int i) { result = RawChildIndex(Raw::ParamBlockParam(i)) }
+
+ChildIndex paramAttr(int i) { result = ParamAttr(i) }
+
+ChildIndex paramDefaultVal() { result = ParamDefaultVal() }
+
+ChildIndex parenExprExpr() { result = RawChildIndex(Raw::ParenExprExpr()) }
+
+ChildIndex pipelineComp(int i) { result = RawChildIndex(Raw::PipelineComp(i)) }
+
+ChildIndex pipelineChainLeft() { result = RawChildIndex(Raw::PipelineChainLeft()) }
+
+ChildIndex pipelineChainRight() { result = RawChildIndex(Raw::PipelineChainRight()) }
+
+ChildIndex returnStmtPipeline() { result = RawChildIndex(Raw::ReturnStmtPipeline()) }
+
+ChildIndex scriptBlockUsing(int i) { result = RawChildIndex(Raw::ScriptBlockUsing(i)) }
+
+ChildIndex scriptBlockParamBlock() { result = RawChildIndex(Raw::ScriptBlockParamBlock()) }
+
+ChildIndex scriptBlockBeginBlock() { result = RawChildIndex(Raw::ScriptBlockBeginBlock()) }
+
+ChildIndex scriptBlockCleanBlock() { result = RawChildIndex(Raw::ScriptBlockCleanBlock()) }
+
+ChildIndex scriptBlockDynParamBlock() { result = RawChildIndex(Raw::ScriptBlockDynParamBlock()) }
+
+ChildIndex scriptBlockEndBlock() { result = RawChildIndex(Raw::ScriptBlockEndBlock()) }
+
+ChildIndex scriptBlockProcessBlock() { result = RawChildIndex(Raw::ScriptBlockProcessBlock()) }
+
+ChildIndex scriptBlockExprBody() { result = RawChildIndex(Raw::ScriptBlockExprBody()) }
+
+ChildIndex scriptBlockAttr(int i) { result = ScriptBlockAttr(i) }
+
+ChildIndex trapStmtBody() { result = RawChildIndex(Raw::TrapStmtBody()) }
+
+ChildIndex trapStmtTypeConstraint() { result = RawChildIndex(Raw::TrapStmtTypeConstraint()) }
+
+ChildIndex redirectionExpr() { result = RawChildIndex(Raw::RedirectionExpr()) }
+
+ChildIndex funParam(int i) { result = FunParam(i) }
+
+ChildIndex stmtBlockStmt(int i) { result = RawChildIndex(Raw::StmtBlockStmt(i)) }
+
+ChildIndex stmtBlockTrapStmt(int i) { result = RawChildIndex(Raw::StmtBlockTrapStmt(i)) }
+
+ChildIndex expandableSubExprExpr() { result = RawChildIndex(Raw::ExpandableSubExprExpr()) }
+
+ChildIndex switchStmtCond() { result = RawChildIndex(Raw::SwitchStmtCond()) }
+
+ChildIndex switchStmtDefault() { result = RawChildIndex(Raw::SwitchStmtDefault()) }
+
+ChildIndex switchStmtCase(int i) { result = RawChildIndex(Raw::SwitchStmtCase(i)) }
+
+ChildIndex switchStmtPat(int i) { result = RawChildIndex(Raw::SwitchStmtPat(i)) }
+
+ChildIndex condExprCond() { result = RawChildIndex(Raw::CondExprCond()) }
+
+ChildIndex condExprTrue() { result = RawChildIndex(Raw::CondExprTrue()) }
+
+ChildIndex condExprFalse() { result = RawChildIndex(Raw::CondExprFalse()) }
+
+ChildIndex throwStmtPipeline() { result = RawChildIndex(Raw::ThrowStmtPipeline()) }
+
+ChildIndex tryStmtBody() { result = RawChildIndex(Raw::TryStmtBody()) }
+
+ChildIndex tryStmtCatchClause(int i) { result = RawChildIndex(Raw::TryStmtCatchClause(i)) }
+
+ChildIndex tryStmtFinally() { result = RawChildIndex(Raw::TryStmtFinally()) }
+
+ChildIndex typeStmtMember(int i) { result = RawChildIndex(Raw::TypeStmtMember(i)) }
+
+ChildIndex typeStmtBaseType(int i) { result = RawChildIndex(Raw::TypeStmtBaseType(i)) }
+
+ChildIndex unaryExprOp() { result = RawChildIndex(Raw::UnaryExprOp()) }
+
+ChildIndex usingExprExpr() { result = RawChildIndex(Raw::UsingExprExpr()) }
+
+ChildIndex whileStmtCond() { result = RawChildIndex(Raw::WhileStmtCond()) }
+
+ChildIndex whileStmtBody() { result = RawChildIndex(Raw::WhileStmtBody()) }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Command.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Command.qll
new file mode 100644
index 000000000000..fb8b93ff9c15
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Command.qll
@@ -0,0 +1,147 @@
+private import AstImport
+
+class CmdCall extends CallExpr, TCmd {
+ final override string getName() { result = getRawAst(this).(Raw::Cmd).getCommandName() }
+
+ final override Expr getArgument(int i) { synthChild(getRawAst(this), cmdArgument(i), result) }
+
+ final override Expr getCallee() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, cmdCallee(), result)
+ or
+ not synthChild(r, cmdCallee(), _) and
+ result = getResultAst(r.(Raw::Cmd).getCallee())
+ )
+ }
+
+ private predicate isNamedArgument(int i, string name) {
+ any(Synthesis s).isNamedArgument(this, i, name)
+ }
+
+ private predicate isPositionalArgument(int i) {
+ exists(this.getArgument(i)) and
+ not this.isNamedArgument(i, _)
+ }
+
+ /** Gets the `i`th positional argument to this command. */
+ final override Expr getPositionalArgument(int i) {
+ result =
+ rank[i + 1](Expr e, int k |
+ this.isPositionalArgument(k) and e = this.getArgument(k)
+ |
+ e order by k
+ )
+ }
+
+ /** Holds if this call has an argument named `name`. */
+ predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
+
+ /** Gets the named argument with the given name. */
+ final override Expr getNamedArgument(string name) {
+ exists(int i |
+ result = this.getArgument(i) and
+ this.isNamedArgument(i, name)
+ )
+ }
+
+ override Redirection getRedirection(int i) {
+ // TODO: Is this weird given that there's also another redirection on Expr?
+ exists(ChildIndex index, Raw::Ast r | index = cmdRedirection(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::Cmd).getRedirection(i))
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = cmdCallee() and
+ result = this.getCallee()
+ or
+ exists(int index |
+ i = cmdArgument(index) and
+ result = this.getArgument(index)
+ or
+ i = cmdRedirection(index) and
+ result = this.getRedirection(index)
+ )
+ }
+}
+
+/** A call to operator `&`. */
+class CallOperator extends CmdCall {
+ CallOperator() { getRawAst(this) instanceof Raw::CallOperator }
+
+ Expr getCommand() { result = this.getArgument(0) }
+}
+
+/** A call to the dot-sourcing `.`. */
+class DotSourcingOperator extends CmdCall {
+ DotSourcingOperator() { getRawAst(this) instanceof Raw::DotSourcingOperator }
+
+ Expr getPath() { result = this.getArgument(0) }
+}
+
+class JoinPath extends CmdCall {
+ JoinPath() { this.getName().toLowerCase() = "join-path" }
+
+ Expr getPath() {
+ result = this.getNamedArgument("path")
+ or
+ not this.hasNamedArgument("path") and
+ result = this.getPositionalArgument(0)
+ }
+
+ Expr getChildPath() {
+ result = this.getNamedArgument("childpath")
+ or
+ not this.hasNamedArgument("childpath") and
+ result = this.getPositionalArgument(1)
+ }
+}
+
+class SplitPath extends CmdCall {
+ SplitPath() { this.getName().toLowerCase() = "split-path" }
+
+ Expr getPath() {
+ result = this.getNamedArgument("path")
+ or
+ not this.hasNamedArgument("path") and
+ result = this.getPositionalArgument(0)
+ or
+ // TODO: This should not be allowed, but I've seen code doing it and somehow it works
+ result = this.getNamedArgument("parent")
+ }
+
+ predicate isParent() { this.hasNamedArgument("parent") }
+
+ predicate isLeaf() { this.hasNamedArgument("leaf") }
+
+ predicate isNoQualifier() { this.hasNamedArgument("noqualifier") }
+
+ predicate isQualifier() { this.hasNamedArgument("qualifier") }
+
+ predicate isResolve() { this.hasNamedArgument("resolve") }
+
+ predicate isExtension() { this.hasNamedArgument("extension") }
+
+ predicate isLeafBaseName() { this.hasNamedArgument("leafbasename") }
+}
+
+class GetVariable extends CmdCall {
+ GetVariable() { this.getName().toLowerCase() = "get-variable" }
+
+ Expr getVariable() { result = this.getPositionalArgument(0) }
+
+ predicate isGlobalScope() { this.hasNamedArgument("global") }
+
+ predicate isLocalScope() { this.hasNamedArgument("local") }
+
+ predicate isScriptScope() { this.hasNamedArgument("script") }
+
+ predicate isPrivateScope() { this.hasNamedArgument("private") }
+
+ predicate isNumbered(Expr e) { e = this.getNamedArgument("scope") }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/CommentEntity.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/CommentEntity.qll
new file mode 100644
index 000000000000..136c3346b3fb
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/CommentEntity.qll
@@ -0,0 +1,2 @@
+private import AstImport
+import Raw.CommentEntity
\ No newline at end of file
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Configuration.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Configuration.qll
new file mode 100644
index 000000000000..7856efb5d946
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Configuration.qll
@@ -0,0 +1,31 @@
+private import AstImport
+
+class Configuration extends Stmt, TConfiguration {
+ override string toString() { result = this.getName().toString() }
+
+ Expr getName() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, configurationName(), result)
+ or
+ not synthChild(r, configurationName(), _) and
+ result = getResultAst(r.(Raw::Configuration).getName())
+ )
+ }
+
+ ScriptBlockExpr getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, configurationBody(), result)
+ or
+ not synthChild(r, configurationBody(), _) and
+ result = getResultAst(r.(Raw::Configuration).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = configurationName() and result = this.getName()
+ or
+ i = configurationBody() and result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Constant.qll
similarity index 71%
rename from powershell/ql/lib/semmle/code/powershell/ConstantExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Constant.qll
index 9c9e8b7f2002..f39a9bdfff7a 100644
--- a/powershell/ql/lib/semmle/code/powershell/ConstantExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Constant.qll
@@ -1,25 +1,19 @@
-import powershell
-
-class ConstExpr extends @constant_expression, BaseConstExpr {
- override SourceLocation getLocation() { constant_expression_location(this, result) }
-
- override string getType() { constant_expression(this, result) }
-
- override StringLiteral getValue() { constant_expression_value(this, result) }
-}
+private import AstImport
private newtype TConstantValue =
TConstInteger(int value) {
- exists(ConstExpr ce | ce.getType() = "Int32" and ce.getValue().getValue().toInt() = value)
+ exists(Raw::ConstExpr ce | ce.getType() = "Int32" and ce.getValue().getValue().toInt() = value)
or
value = [0 .. 10] // needed for `trackKnownValue` in `DataFlowPrivate`
} or
TConstDouble(float double) {
- exists(ConstExpr ce | ce.getType() = "Double" and ce.getValue().getValue().toFloat() = double)
+ exists(Raw::ConstExpr ce |
+ ce.getType() = "Double" and ce.getValue().getValue().toFloat() = double
+ )
} or
- TConstString(string value) { exists(StringLiteral sl | sl.getValue() = value) } or
+ TConstString(string value) { exists(Raw::StringLiteral sl | sl.getValue() = value) } or
TConstBoolean(boolean value) {
- exists(VarAccess va |
+ exists(Raw::VarAccess va |
value = true and
va.getUserPath() = "true"
or
@@ -67,7 +61,9 @@ class ConstInteger extends ConstantValue, TConstInteger {
final override string serialize() { result = this.getValue() }
- final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
+ final override ConstExpr getAnExpr() {
+ result.getValueString() = this.getValue()
+ }
}
/** A constant floating point value. */
@@ -82,7 +78,12 @@ class ConstDouble extends ConstantValue, TConstDouble {
)
}
- final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
+ final override ConstExpr getAnExpr() {
+ exists(Raw::ConstExpr ce |
+ ce.getValue().getValue() = this.getValue() and
+ result = fromRaw(ce)
+ )
+ }
}
/** A constant string value. */
@@ -95,7 +96,7 @@ class ConstString extends ConstantValue, TConstString {
result = "\"" + this.asString().replaceAll("\"", "\\\"") + "\""
}
- final override BaseConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
+ final override StringConstExpr getAnExpr() { result.getValueString() = this.getValue() }
}
/** A constant boolean value. */
@@ -106,13 +107,7 @@ class ConstBoolean extends ConstantValue, TConstBoolean {
final override string serialize() { result = this.getValue() }
- final override VarAccess getAnExpr() {
- this.asBoolean() = true and
- result.getUserPath() = "true"
- or
- this.asBoolean() = false and
- result.getUserPath() = "false"
- }
+ final override BoolLiteral getAnExpr() { result.getBoolValue() = this.asBoolean() }
}
/** The constant null value. */
@@ -123,5 +118,5 @@ class NullConst extends ConstantValue, TNull {
final override string serialize() { result = this.getValue() }
- final override VarAccess getAnExpr() { result.getUserPath() = "null" }
+ final override NullLiteral getAnExpr() { any() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ConstantExpression.qll
new file mode 100644
index 000000000000..d2387c761b72
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ConstantExpression.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class ConstExpr extends Expr, TConstExpr {
+ string getValueString() { result = getRawAst(this).(Raw::ConstExpr).getValue().getValue() }
+
+ override string toString() { result = this.getValue().getValue() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ContinueStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ContinueStmt.qll
new file mode 100644
index 000000000000..257378bbbb49
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ContinueStmt.qll
@@ -0,0 +1,5 @@
+private import AstImport
+
+class ContinueStmt extends Stmt, TContinueStmt {
+ override string toString() { result = "continue" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ConvertExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ConvertExpr.qll
new file mode 100644
index 000000000000..e799435c843b
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ConvertExpr.qll
@@ -0,0 +1,42 @@
+private import AstImport
+
+class ConvertExpr extends AttributedExprBase, TConvertExpr {
+ override string toString() { result = "[...]..." }
+
+ final override Expr getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, convertExprExpr(), result)
+ or
+ not synthChild(r, convertExprExpr(), _) and
+ result = getResultAst(r.(Raw::ConvertExpr).getExpr())
+ )
+ }
+
+ TypeConstraint getType() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, convertExprType(), result)
+ or
+ not synthChild(r, convertExprType(), _) and
+ result = getResultAst(r.(Raw::ConvertExpr).getType())
+ )
+ }
+
+ final override AttributeBase getAttribute() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, convertExprAttr(), result)
+ or
+ not synthChild(r, convertExprAttr(), _) and
+ result = getResultAst(r.(Raw::ConvertExpr).getAttribute())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = convertExprExpr() and result = this.getExpr()
+ or
+ i = convertExprType() and result = this.getType()
+ or
+ i = convertExprAttr() and result = this.getAttribute()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/DataStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/DataStmt.qll
new file mode 100644
index 000000000000..cf32bfb84572
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/DataStmt.qll
@@ -0,0 +1,37 @@
+private import AstImport
+
+class DataStmt extends Stmt, TDataStmt {
+ override string toString() { result = "data {...}" }
+
+ Expr getCmdAllowed(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = dataStmtCmdAllowed(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::DataStmt).getCmdAllowed(i))
+ )
+ }
+
+ Expr getACmdAllowed() { result = this.getCmdAllowed(_) }
+
+ StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, dataStmtBody(), result)
+ or
+ not synthChild(r, dataStmtBody(), _) and
+ result = getResultAst(r.(Raw::DataStmt).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = dataStmtBody() and
+ result = this.getBody()
+ or
+ exists(int index |
+ i = dataStmtCmdAllowed(index) and
+ result = this.getCmdAllowed(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/DoUntilStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/DoUntilStmt.qll
new file mode 100644
index 000000000000..415a248a09d3
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/DoUntilStmt.qll
@@ -0,0 +1,31 @@
+private import AstImport
+
+class DoUntilStmt extends LoopStmt, TDoUntilStmt {
+ override string toString() { result = "do...until..." }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, doUntilStmtCond(), result)
+ or
+ not synthChild(r, doUntilStmtCond(), _) and
+ result = getResultAst(r.(Raw::DoUntilStmt).getCondition())
+ )
+ }
+
+ final override StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, doUntilStmtBody(), result)
+ or
+ not synthChild(r, doUntilStmtBody(), _) and
+ result = getResultAst(r.(Raw::DoUntilStmt).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = doUntilStmtCond() and result = this.getCondition()
+ or
+ i = doUntilStmtBody() and result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/DoWhileStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/DoWhileStmt.qll
new file mode 100644
index 000000000000..ab7099cefcb7
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/DoWhileStmt.qll
@@ -0,0 +1,33 @@
+private import AstImport
+
+class DoWhileStmt extends LoopStmt, TDoWhileStmt {
+ override string toString() { result = "do...while..." }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, doWhileStmtCond(), result)
+ or
+ not synthChild(r, doWhileStmtCond(), _) and
+ result = getResultAst(r.(Raw::DoWhileStmt).getCondition())
+ )
+ }
+
+ final override StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, doWhileStmtBody(), result)
+ or
+ not synthChild(r, doWhileStmtBody(), _) and
+ result = getResultAst(r.(Raw::DoWhileStmt).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = doWhileStmtCond() and
+ result = this.getCondition()
+ or
+ i = doWhileStmtBody() and
+ result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/DynamicStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/DynamicStmt.qll
new file mode 100644
index 000000000000..34bef60f2da1
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/DynamicStmt.qll
@@ -0,0 +1,45 @@
+private import AstImport
+
+class DynamicStmt extends Stmt, TDynamicStmt {
+ override string toString() { result = "&..." }
+
+ Expr getName() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, dynamicStmtName(), result)
+ or
+ not synthChild(r, dynamicStmtName(), _) and
+ result = getResultAst(r.(Raw::DynamicStmt).getName())
+ )
+ }
+
+ ScriptBlockExpr getScriptBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, dynamicStmtBody(), result)
+ or
+ not synthChild(r, dynamicStmtBody(), _) and
+ result = getResultAst(r.(Raw::DynamicStmt).getScriptBlock())
+ )
+ }
+
+ HashTableExpr getHashTableExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, dynamicStmtBody(), result)
+ or
+ not synthChild(r, dynamicStmtBody(), _) and
+ result = getResultAst(r.(Raw::DynamicStmt).getHashTableExpr())
+ )
+ }
+
+ predicate hasScriptBlock() { exists(this.getScriptBlock()) }
+
+ predicate hasHashTableExpr() { exists(this.getHashTableExpr()) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = dynamicStmtName() and result = this.getName()
+ or
+ i = dynamicStmtBody() and
+ (result = this.getScriptBlock() or result = this.getHashTableExpr())
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/EnvVariable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/EnvVariable.qll
new file mode 100644
index 000000000000..5d61c101bd44
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/EnvVariable.qll
@@ -0,0 +1,11 @@
+private import AstImport
+
+class EnvVariable extends Expr, TEnvVariable {
+ final override string toString() { result = this.getName() }
+
+ string getName() { any(Synthesis s).envVariableName(this, result) }
+}
+
+class SystemDrive extends EnvVariable {
+ SystemDrive() { this.getName() = "systemdrive" }
+}
\ No newline at end of file
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorExpr.qll
new file mode 100644
index 000000000000..154b80e8e920
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorExpr.qll
@@ -0,0 +1,5 @@
+private import AstImport
+
+class ErrorExpr extends Expr, TErrorExpr {
+ final override string toString() { result = "error" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorStmt.qll
new file mode 100644
index 000000000000..8528cf091154
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ErrorStmt.qll
@@ -0,0 +1,5 @@
+private import AstImport
+
+class ErrorStmt extends Stmt, TErrorStmt {
+ final override string toString() { result = "error" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ExitStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExitStmt.qll
new file mode 100644
index 000000000000..07cd97f343cd
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExitStmt.qll
@@ -0,0 +1,22 @@
+private import AstImport
+
+class ExitStmt extends Stmt, TExitStmt {
+ Expr getPipeline() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, exitStmtPipeline(), result)
+ or
+ not synthChild(r, exitStmtPipeline(), _) and
+ result = getResultAst(r.(Raw::ExitStmt).getPipeline())
+ )
+ }
+
+ predicate hasPipeline() { exists(this.getPipeline()) }
+
+ override string toString() { if this.hasPipeline() then result = "exit ..." else result = "exit" }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = exitStmtPipeline() and result = this.getPipeline()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ExpandableStringExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExpandableStringExpression.qll
new file mode 100644
index 000000000000..98eb80f2c154
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExpandableStringExpression.qll
@@ -0,0 +1,31 @@
+private import AstImport
+
+class ExpandableStringExpr extends Expr, TExpandableStringExpr {
+ string getUnexpandedValue() {
+ result = getRawAst(this).(Raw::ExpandableStringExpr).getUnexpandedValue().getValue()
+ }
+
+ override string toString() { result = this.getUnexpandedValue() }
+
+ Expr getExpr(int i) {
+ exists(ChildIndex index, Raw::Ast r |
+ index = expandableStringExprExpr(i) and r = getRawAst(this)
+ |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::ExpandableStringExpr).getExpr(i))
+ )
+ }
+
+ Expr getAnExpr() { result = this.getExpr(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = expandableStringExprExpr(index) and
+ result = this.getExpr(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Expr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Expr.qll
new file mode 100644
index 000000000000..756e467b07a8
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Expr.qll
@@ -0,0 +1,22 @@
+private import AstImport
+
+/**
+ * An expression.
+ *
+ * This is the topmost class in the hierachy of all expression in PowerShell.
+ */
+class Expr extends Ast, TExpr {
+ /** Gets the constant value of this expression, if this is known. */
+ ConstantValue getValue() { result.getAnExpr() = this }
+
+ Redirection getRedirection(int i) { synthChild(getRawAst(this), exprRedirection(i), result) }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = exprRedirection(index) and
+ result = this.getRedirection(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ExprStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExprStmt.qll
new file mode 100644
index 000000000000..3be667f62b46
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ExprStmt.qll
@@ -0,0 +1,16 @@
+private import AstImport
+
+class ExprStmt extends Stmt, TExprStmt {
+ override string toString() { result = "[Stmt] " + this.getExpr().toString() }
+
+ string getName() { result = any(Synthesis s).toString(this) }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = exprStmtExpr() and
+ result = this.getExpr()
+ }
+
+ Expr getExpr() { any(Synthesis s).exprStmtExpr(this, result) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/File.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/File.qll
new file mode 100644
index 000000000000..0f2a89e0f4b5
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/File.qll
@@ -0,0 +1 @@
+import Raw.File
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/FileRedirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/FileRedirection.qll
new file mode 100644
index 000000000000..f3409baf4f08
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/FileRedirection.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class FileRedirection extends Redirection {
+ FileRedirection() { this = TRedirection(any(Raw::FileRedirection r)) }
+
+ override string toString() { result = "FileRedirection" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ForEachStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ForEachStmt.qll
new file mode 100644
index 000000000000..a1abe00bb80d
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ForEachStmt.qll
@@ -0,0 +1,43 @@
+private import AstImport
+
+class ForEachStmt extends LoopStmt, TForEachStmt {
+ override string toString() { result = "forach(... in ...)" }
+
+ final override StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forEachStmtBody(), result)
+ or
+ not synthChild(r, forEachStmtBody(), _) and
+ result = getResultAst(r.(Raw::ForEachStmt).getBody())
+ )
+ }
+
+ // TODO: Should this API change?
+ VarAccess getVarAccess() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forEachStmtVar(), result)
+ or
+ not synthChild(r, forEachStmtVar(), _) and
+ result = getResultAst(r.(Raw::ForEachStmt).getVarAccess())
+ )
+ }
+
+ Expr getIterableExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forEachStmtIter(), result)
+ or
+ not synthChild(r, forEachStmtIter(), _) and
+ result = getResultAst(r.(Raw::ForEachStmt).getIterableExpr())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = forEachStmtVar() and result = this.getVarAccess()
+ or
+ i = forEachStmtIter() and result = this.getIterableExpr()
+ or
+ i = forEachStmtBody() and result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ForStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ForStmt.qll
new file mode 100644
index 000000000000..81de53fc52ec
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ForStmt.qll
@@ -0,0 +1,58 @@
+private import AstImport
+
+class ForStmt extends LoopStmt, TForStmt {
+ override string toString() { result = "for(...;...;...)" }
+
+ Ast getInitializer() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ // TODO: I think this is always an assignment?
+ synthChild(r, forStmtInit(), result)
+ or
+ not synthChild(r, forStmtInit(), _) and
+ result = getResultAst(r.(Raw::ForStmt).getInitializer())
+ )
+ }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forStmtCond(), result)
+ or
+ not synthChild(r, forStmtCond(), _) and
+ result = getResultAst(r.(Raw::ForStmt).getCondition())
+ )
+ }
+
+ Ast getIterator() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forStmtIter(), result)
+ or
+ not synthChild(r, forStmtIter(), _) and
+ result = getResultAst(r.(Raw::ForStmt).getIterator())
+ )
+ }
+
+ final override StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, forStmtBody(), result)
+ or
+ not synthChild(r, forStmtBody(), _) and
+ result = getResultAst(r.(Raw::ForStmt).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = forStmtInit() and
+ result = this.getInitializer()
+ or
+ i = forStmtCond() and
+ result = this.getCondition()
+ or
+ i = forStmtIter() and
+ result = this.getIterator()
+ or
+ i = forStmtBody() and
+ result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Function.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Function.qll
new file mode 100644
index 000000000000..e640fdbaaa4e
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Function.qll
@@ -0,0 +1,15 @@
+private import AstImport
+
+class Function extends FunctionBase, TFunction {
+ final override string getName() { any(Synthesis s).functionName(this, result) }
+
+ final override ScriptBlock getBody() { any(Synthesis s).functionScriptBlock(this, result) }
+
+ final override Parameter getParameter(int i) { result = this.getBody().getParameter(i) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = functionBody() and result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionBase.qll
new file mode 100644
index 000000000000..e530778900e6
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionBase.qll
@@ -0,0 +1,23 @@
+private import AstImport
+private import semmle.code.powershell.controlflow.BasicBlocks
+
+class FunctionBase extends Ast, TFunctionBase {
+ final override string toString() { result = this.getName() }
+
+ string getName() { none() }
+
+ final predicate hasName(string name) { name = this.getName() }
+
+ ScriptBlock getBody() { none() }
+
+ Parameter getParameter(int i) { none() }
+
+ final Parameter getAParameter() { result = this.getParameter(_) }
+
+ /** Note: This always has a result */
+ final PipelineParameter getPipelineParameter() { result = this.getAParameter() }
+
+ final EntryBasicBlock getEntryBasicBlock() { result.getScope() = this.getBody() }
+
+ final int getNumberOfParameters() { result = count(this.getAParameter()) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionDefinition.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionDefinition.qll
new file mode 100644
index 000000000000..9800fb647c6e
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/FunctionDefinition.qll
@@ -0,0 +1,15 @@
+private import AstImport
+
+class FunctionDefinitionStmt extends Stmt, TFunctionDefinitionStmt {
+ FunctionBase getFunction() { synthChild(getRawAst(this), funDefFun(), result) }
+
+ string getName() { result = getRawAst(this).(Raw::FunctionDefinitionStmt).getName() }
+
+ final override string toString() { result = "def of " + this.getName() }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = funDefFun() and result = this.getFunction()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/GotoStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/GotoStmt.qll
new file mode 100644
index 000000000000..af9c48ed97ca
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/GotoStmt.qll
@@ -0,0 +1,18 @@
+private import AstImport
+
+class GotoStmt extends Stmt, TGotoStmt {
+ Expr getLabel() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, gotoStmtLabel(), result)
+ or
+ not synthChild(r, gotoStmtLabel(), _) and
+ result = getResultAst(r.(Raw::GotoStmt).getLabel())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = gotoStmtLabel() and result = this.getLabel()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/HashTable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/HashTable.qll
new file mode 100644
index 000000000000..ec6b914a9dba
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/HashTable.qll
@@ -0,0 +1,51 @@
+private import AstImport
+
+class HashTableExpr extends Expr, THashTableExpr {
+ final override string toString() { result = "${...}" }
+
+ Expr getKey(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = hashTableExprKey(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::HashTableExpr).getKey(i))
+ )
+ }
+
+ Expr getAKey() { result = this.getKey(_) }
+
+ Expr getValue(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = hashTableExprStmt(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::HashTableExpr).getStmt(i))
+ )
+ }
+
+ Expr getValueFromKey(Expr key) {
+ exists(int i |
+ this.getKey(i) = key and
+ result = this.getValue(i)
+ )
+ }
+
+ Expr getAValue() { result = this.getValue(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = hashTableExprKey(index) and
+ result = this.getKey(index)
+ or
+ i = hashTableExprStmt(index) and
+ result = this.getValue(index)
+ )
+ }
+
+ predicate hasEntry(int i, Expr key, Expr value) {
+ this.getKey(i) = key and
+ this.getValue(i) = value
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/If.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/If.qll
new file mode 100644
index 000000000000..94192397060c
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/If.qll
@@ -0,0 +1,57 @@
+private import AstImport
+
+class If extends Expr, TIf {
+ override string toString() {
+ if this.hasElse() then result = "if (...) {...} else {...}" else result = "if (...) {...}"
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = ifStmtElse() and
+ result = this.getElse()
+ or
+ exists(int index |
+ i = ifStmtCond(index) and
+ result = this.getCondition(index)
+ or
+ i = ifStmtThen(index) and
+ result = this.getThen(index)
+ )
+ }
+
+ Expr getCondition(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = ifStmtCond(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::IfStmt).getCondition(i))
+ )
+ }
+
+ Expr getACondition() { result = this.getCondition(_) }
+
+ int getNumberOfConditions() { result = count(this.getACondition()) }
+
+ StmtBlock getThen(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = ifStmtThen(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::IfStmt).getThen(i))
+ )
+ }
+
+ StmtBlock getAThen() { result = this.getThen(_) }
+
+ StmtBlock getElse() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, ifStmtElse(), result)
+ or
+ not synthChild(r, ifStmtElse(), _) and
+ result = getResultAst(r.(Raw::IfStmt).getElse())
+ )
+ }
+
+ predicate hasElse() { exists(this.getElse()) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/IndexExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/IndexExpr.qll
new file mode 100644
index 000000000000..9d52c12485c0
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/IndexExpr.qll
@@ -0,0 +1,51 @@
+private import AstImport
+
+class IndexExpr extends Expr, TIndexExpr {
+ override string toString() { result = "...[...]" }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = indexExprIndex() and result = this.getIndex()
+ or
+ i = indexExprBase() and result = this.getBase()
+ }
+
+ Expr getIndex() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, indexExprIndex(), result)
+ or
+ not synthChild(r, indexExprIndex(), _) and
+ result = getResultAst(r.(Raw::IndexExpr).getIndex())
+ )
+ }
+
+ Expr getBase() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, indexExprBase(), result)
+ or
+ not synthChild(r, indexExprBase(), _) and
+ result = getResultAst(r.(Raw::IndexExpr).getBase())
+ )
+ }
+
+ predicate isNullConditional() { getRawAst(this).(Raw::IndexExpr).isNullConditional() }
+
+ predicate isExplicitWrite(Ast assignment) {
+ explicitAssignment(getRawAst(this), getRawAst(assignment))
+ }
+
+ predicate isImplicitWrite() {
+ implicitAssignment(getRawAst(this))
+ }
+}
+
+/** An `IndexExpr` that is being written to. */
+class IndexExprWriteAccess extends IndexExpr {
+ IndexExprWriteAccess() { this.isExplicitWrite(_) or this.isImplicitWrite() }
+}
+
+/** An `IndexExpr` that is being read from. */
+class IndexExprReadAccess extends IndexExpr {
+ IndexExprReadAccess() { not this instanceof IndexExprWriteAccess }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Internal.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Internal.qll
new file mode 100644
index 000000000000..75fb48651014
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Internal.qll
@@ -0,0 +1,96 @@
+module Private {
+ import ChildIndex
+ import Variable::Private
+}
+
+module Public {
+ import File
+ import Location
+ import SourceLocation
+ import Ast
+ import Statement
+ import Expr
+ import PipelineChain
+ import ConstantExpression
+ import Attribute
+ import AttributeBase
+ import NamedAttributeArgument
+ import FunctionBase
+ import Function
+ import FunctionDefinition
+ import TypeConstraint
+ import ModuleSpecification
+ import NamedBlock
+ import ScriptBlock
+ import AssignmentStatement
+ import BinaryExpression
+ import UnaryExpression
+ import ScriptBlockExpr
+ import TernaryExpression
+ import UsingExpression
+ import TrapStatement
+ import StatementBlock
+ import ArrayExpression
+ import ArrayLiteral
+ import Redirection
+ import FileRedirection
+ import MergingRedirection
+ import LoopStmt
+ import DoWhileStmt
+ import DoUntilStmt
+ import WhileStmt
+ import ForStmt
+ import ForEachStmt
+ import GotoStmt
+ import ContinueStmt
+ import BreakStmt
+ import ReturnStmt
+ import UsingStmt
+ import ThrowStmt
+ import ErrorStmt
+ import TypeDefinitionStmt
+ import Member
+ import PropertyMember
+ import TryStmt
+ import If
+ import SwitchStmt
+ import ThisExpr
+ import ExitStmt
+ import DynamicStmt
+ import DataStmt
+ import Configuration
+ import CatchClause
+ import Parameter
+ import ExpandableStringExpression
+ import TypeExpression
+ import ParenExpr
+ import Pipeline
+ import StringConstantExpression
+ import MemberExpr
+ import InvokeMemberExpression
+ import ObjectCreation
+ import SubExpression
+ import ErrorExpr
+ import ConvertExpr
+ import IndexExpr
+ import HashTable
+ import Variable::Public
+ import CallExpr
+ import Command
+ import ExprStmt
+ import Constant
+ import AttributeBase
+ import Method
+ import AttributedExpr
+ import AttributedExprBase
+ import Scopes
+ import BoolLiteral
+ import NullLiteral
+ import Operation
+ import Literal
+ import EnvVariable
+ import Type
+ import AutomaticVariable
+ import Operation
+ import CommentEntity
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/InvokeMemberExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/InvokeMemberExpression.qll
new file mode 100644
index 000000000000..c57b4a6fe42f
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/InvokeMemberExpression.qll
@@ -0,0 +1,74 @@
+private import AstImport
+
+class InvokeMemberExpr extends CallExpr, TInvokeMemberExpr {
+ final override string getName() { result = getRawAst(this).(Raw::InvokeMemberExpr).getName() }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = invokeMemberExprQual() and
+ result = this.getQualifier()
+ or
+ i = invokeMemberExprCallee() and
+ result = this.getCallee()
+ or
+ exists(int index |
+ i = invokeMemberExprArg(index) and
+ result = this.getArgument(index)
+ )
+ }
+
+ final override Expr getCallee() {
+ exists(Raw::Ast r | r = getRawAst(this) and r = getRawAst(this) |
+ synthChild(r, invokeMemberExprCallee(), result)
+ or
+ not synthChild(r, invokeMemberExprCallee(), _) and
+ result = getResultAst(r.(Raw::InvokeMemberExpr).getCallee())
+ )
+ }
+
+ final override Expr getArgument(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = invokeMemberExprArg(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::InvokeMemberExpr).getArgument(i))
+ )
+ }
+
+ final override Expr getPositionalArgument(int i) {
+ // All arguments are positional in an InvokeMemberExpr
+ result = this.getArgument(i)
+ }
+
+ final override Expr getNamedArgument(string name) { none() }
+
+ final override Expr getQualifier() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, invokeMemberExprQual(), result)
+ or
+ not synthChild(r, invokeMemberExprQual(), _) and
+ result = getResultAst(r.(Raw::InvokeMemberExpr).getQualifier())
+ )
+ }
+
+ override predicate isStatic() { getRawAst(this).(Raw::InvokeMemberExpr).isStatic() }
+}
+
+/**
+ * A call to a constructor. For example:
+ *
+ * ```powershell
+ * [System.IO.FileInfo]::new("C:\\file.txt")
+ * ```
+ */
+class ConstructorCall extends InvokeMemberExpr {
+ TypeNameExpr typename;
+
+ ConstructorCall() {
+ this.isStatic() and typename = this.getQualifier() and this.getName() = "new"
+ }
+
+ /** Gets the name of the type being constructed by this constructor call. */
+ string getConstructedTypeName() { result = typename.getName() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Literal.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Literal.qll
new file mode 100644
index 000000000000..9e8ad3d44698
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Literal.qll
@@ -0,0 +1,3 @@
+private import AstImport
+
+class Literal extends Expr, TLiteral { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Location.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Location.qll
new file mode 100644
index 000000000000..687ffe8b4152
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Location.qll
@@ -0,0 +1 @@
+import Raw.Location
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/LoopStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/LoopStmt.qll
new file mode 100644
index 000000000000..d7ca83ab51a4
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/LoopStmt.qll
@@ -0,0 +1,5 @@
+private import AstImport
+
+class LoopStmt extends Stmt, TLoopStmt {
+ StmtBlock getBody() { none() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Member.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Member.qll
new file mode 100644
index 000000000000..e650ae947548
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Member.qll
@@ -0,0 +1,41 @@
+private import AstImport
+
+class Member extends Ast, TMember {
+ string getName() {
+ result = getRawAst(this).(Raw::Member).getName()
+ or
+ any(Synthesis s).memberName(this, result)
+ }
+
+ Type getDeclaringType() { result.getAMember() = this }
+
+ final Attribute getAttribute(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = memberAttr(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::Member).getAttribute(i))
+ )
+ }
+
+ final TypeConstraint getTypeConstraint() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, memberTypeConstraint(), result)
+ or
+ not synthChild(r, memberTypeConstraint(), _) and
+ result = getResultAst(r.(Raw::Member).getTypeConstraint())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = memberAttr(index) and
+ result = this.getAttribute(index)
+ )
+ or
+ i = memberTypeConstraint() and
+ result = this.getTypeConstraint()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/MemberExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/MemberExpr.qll
new file mode 100644
index 000000000000..0af48cd6485f
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/MemberExpr.qll
@@ -0,0 +1,58 @@
+private import AstImport
+
+class MemberExpr extends Expr, TMemberExpr {
+ Expr getQualifier() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, memberExprQual(), result)
+ or
+ not synthChild(r, memberExprQual(), _) and
+ result = getResultAst(r.(Raw::MemberExpr).getQualifier())
+ )
+ }
+
+ Expr getMemberExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, memberExprMember(), result)
+ or
+ not synthChild(r, memberExprMember(), _) and
+ result = getResultAst(r.(Raw::MemberExpr).getMember())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = memberExprQual() and result = this.getQualifier()
+ or
+ i = memberExprMember() and result = this.getMemberExpr()
+ }
+
+ /** Gets the name of the member being looked up, if any. */
+ string getMemberName() {
+ result = getRawAst(this).(Raw::MemberExpr).getMember().(Raw::StringConstExpr).getValue().getValue()
+ }
+
+ predicate isNullConditional() { getRawAst(this).(Raw::MemberExpr).isNullConditional() }
+
+ predicate isStatic() { getRawAst(this).(Raw::MemberExpr).isStatic() }
+
+ final override string toString() { result = this.getMemberName() }
+
+ predicate isExplicitWrite(Ast assignment) {
+ explicitAssignment(getRawAst(this), getRawAst(assignment))
+ }
+
+ predicate isImplicitWrite() {
+ implicitAssignment(getRawAst(this))
+ }
+}
+
+/** A `MemberExpr` that is being written to. */
+class MemberExprWriteAccess extends MemberExpr {
+ MemberExprWriteAccess() { this.isExplicitWrite(_) or this.isImplicitWrite() }
+}
+
+/** A `MemberExpr` that is being read from. */
+class MemberExprReadAccess extends MemberExpr {
+ MemberExprReadAccess() { not this instanceof MemberExprWriteAccess }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/MergingRedirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/MergingRedirection.qll
new file mode 100644
index 000000000000..29a8fde86bd2
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/MergingRedirection.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class MergingRedirection extends Redirection {
+ MergingRedirection() { this = TRedirection(any(Raw::MergingRedirection r)) }
+
+ override string toString() { result = "MergingRedirection" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Method.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Method.qll
new file mode 100644
index 000000000000..ebe47dd9b9d1
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Method.qll
@@ -0,0 +1,35 @@
+private import AstImport
+
+class Method extends Member, FunctionBase, TMethod {
+ final override string getName() { result = Member.super.getName() }
+
+ final override ScriptBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, methodBody(), result)
+ or
+ not synthChild(r, methodBody(), _) and
+ result = getResultAst(r.(Raw::Method).getBody())
+ )
+ }
+
+ final override Parameter getParameter(int i) { result = this.getBody().getParameter(i) }
+
+ final override Location getLocation() { result = getRawAst(this).(Raw::Method).getLocation() }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = methodBody() and result = this.getBody()
+ }
+
+ predicate isConstructor() { getRawAst(this).(Raw::Method).isConstructor() }
+
+ ThisParameter getThisParameter() {
+ result.getFunction() = this
+ }
+}
+
+/** A constructor definition. */
+class Constructor extends Method {
+ Constructor() { this.isConstructor() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ModuleSpecification.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ModuleSpecification.qll
new file mode 100644
index 000000000000..c7641774c3a4
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ModuleSpecification.qll
@@ -0,0 +1 @@
+import Raw.ModuleSpecification
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedAttributeArgument.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedAttributeArgument.qll
new file mode 100644
index 000000000000..57d8722e8b38
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedAttributeArgument.qll
@@ -0,0 +1,24 @@
+private import AstImport
+
+class NamedAttributeArgument extends Ast, TNamedAttributeArgument {
+ final override string toString() { result = this.getName() }
+
+ string getName() { result = getRawAst(this).(Raw::NamedAttributeArgument).getName() }
+
+ predicate hasName(string s) { this.getName() = s }
+
+ Expr getValue() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, namedAttributeArgVal(), result)
+ or
+ not synthChild(r, namedAttributeArgVal(), _) and
+ result = getResultAst(r.(Raw::NamedAttributeArgument).getValue())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = namedAttributeArgVal() and result = this.getValue()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedBlock.qll
new file mode 100644
index 000000000000..a23106fff648
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/NamedBlock.qll
@@ -0,0 +1,56 @@
+private import AstImport
+
+class NamedBlock extends Ast, TNamedBlock {
+ override string toString() { result = "{...}" }
+
+ Stmt getStmt(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = namedBlockStmt(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::NamedBlock).getStmt(i))
+ )
+ }
+
+ TrapStmt getTrapStmt(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = namedBlockTrap(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::NamedBlock).getTrap(i))
+ )
+ }
+
+ Stmt getAStmt() { result = this.getStmt(_) }
+
+ TrapStmt getATrapStmt() { result = this.getTrapStmt(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = namedBlockStmt(index) and
+ result = this.getStmt(index)
+ or
+ i = namedBlockTrap(index) and
+ result = this.getTrapStmt(index)
+ )
+ }
+}
+
+/** A `process` block. */
+class ProcessBlock extends NamedBlock {
+ ScriptBlock scriptBlock;
+
+ ProcessBlock() { scriptBlock.getProcessBlock() = this }
+
+ ScriptBlock getScriptBlock() { result = scriptBlock }
+
+ PipelineParameter getPipelineParameter() {
+ result = this.getEnclosingFunction().getPipelineParameter()
+ }
+
+ PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
+ result = scriptBlock.getEnclosingFunction().getAParameter()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/NullLiteral.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/NullLiteral.qll
new file mode 100644
index 000000000000..5bba004042ca
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/NullLiteral.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class NullLiteral extends Literal, TNullLiteral {
+ final override string toString() { result = this.getValue().toString() }
+
+ final override ConstantValue getValue() { result.isNull() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ObjectCreation.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ObjectCreation.qll
new file mode 100644
index 000000000000..5cb392762599
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ObjectCreation.qll
@@ -0,0 +1,48 @@
+import powershell
+
+abstract private class AbstractObjectCreation extends CallExpr {
+ /** The name of the type of the object being constructed. */
+ abstract string getConstructedTypeName();
+
+ abstract Expr getConstructedTypeExpr();
+}
+
+/**
+ * An object creation from a call to a constructor. For example:
+ * ```powershell
+ * [System.IO.FileInfo]::new("C:\\file.txt")
+ * ```
+ */
+class NewObjectCreation extends AbstractObjectCreation, ConstructorCall {
+ final override string getConstructedTypeName() {
+ result = ConstructorCall.super.getConstructedTypeName()
+ }
+
+ final override Expr getConstructedTypeExpr() { result = typename }
+}
+
+/**
+ * An object creation from a call to `New-Object`. For example:
+ * ```powershell
+ * New-Object -TypeName System.IO.FileInfo -ArgumentList "C:\\file.txt"
+ * ```
+ */
+class DotNetObjectCreation extends AbstractObjectCreation, CmdCall {
+ DotNetObjectCreation() { this.getName() = "New-Object" }
+
+ final override string getConstructedTypeName() {
+ result = this.getConstructedTypeExpr().(StringConstExpr).getValueString()
+ }
+
+ final override Expr getConstructedTypeExpr() {
+ // Either it's the named argument `TypeName`
+ result = CmdCall.super.getNamedArgument("TypeName")
+ or
+ // Or it's the first positional argument if that's the named argument
+ not CmdCall.super.hasNamedArgument("TypeName") and
+ result = CmdCall.super.getPositionalArgument(0) and
+ result = CmdCall.super.getNamedArgument(["ArgumentList", "Property"])
+ }
+}
+
+final class ObjectCreation = AbstractObjectCreation;
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Operation.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Operation.qll
new file mode 100644
index 000000000000..a2e1e4547e54
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Operation.qll
@@ -0,0 +1,19 @@
+private import AstImport
+
+class Operation extends Expr, TOperation {
+ Expr getAnOperand() { none() }
+
+ int getKind() { none() }
+}
+
+class BinaryOperation extends BinaryExpr, Operation {
+ final override Expr getAnOperand() { result = BinaryExpr.super.getAnOperand() }
+
+ final override int getKind() { result = BinaryExpr.super.getKind() }
+}
+
+class UnaryOperation extends UnaryExpr, Operation {
+ final override Expr getAnOperand() { result = UnaryExpr.super.getOperand() }
+
+ final override int getKind() { result = UnaryExpr.super.getKind() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Parameter.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Parameter.qll
new file mode 100644
index 000000000000..8a0a82f06ab2
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Parameter.qll
@@ -0,0 +1,56 @@
+private import AstImport
+
+class Parameter extends Variable instanceof ParameterImpl {
+ string getName() { result = super.getNameImpl() }
+
+ final predicate hasName(string name) { name = this.getName() }
+
+ override Ast getChild(ChildIndex childIndex) {
+ result = Variable.super.getChild(childIndex)
+ or
+ childIndex = paramDefaultVal() and result = this.getDefaultValue()
+ or
+ exists(int index |
+ childIndex = paramAttr(index) and
+ result = this.getAttribute(index)
+ )
+ }
+
+ Expr getDefaultValue() { synthChild(getRawAst(this), paramDefaultVal(), result) }
+
+ AttributeBase getAttribute(int index) { synthChild(getRawAst(this), paramAttr(index), result) }
+
+ AttributeBase getAnAttribute() { result = this.getAttribute(_) }
+
+ predicate hasDefaultValue() { exists(this.getDefaultValue()) }
+
+ FunctionBase getFunction() { result.getAParameter() = this }
+
+ int getIndex() { this.getFunction().getParameter(result) = this }
+
+ /** ..., if any. */
+ string getStaticType() { any(Synthesis s).parameterStaticType(this, result) }
+}
+
+class ThisParameter extends Parameter instanceof ThisParameterImpl { }
+
+class PipelineParameter extends Parameter {
+ PipelineParameter() { any(Synthesis s).isPipelineParameter(this) }
+}
+
+class PipelineByPropertyNameParameter extends Parameter {
+ PipelineByPropertyNameParameter() {
+ exists(NamedAttributeArgument namedAttribute |
+ this.getAnAttribute().(Attribute).getANamedArgument() = namedAttribute and
+ namedAttribute.getName().toLowerCase() = "valuefrompipelinebypropertyname"
+ |
+ namedAttribute.getValue().getValue().asBoolean() = true
+ or
+ not exists(namedAttribute.getValue().getValue().asBoolean())
+ )
+ }
+
+ string getPropertyName() { result = this.getName() }
+
+ PipelineByPropertyNameIteratorVariable getIteratorVariable() { result.getParameter() = this }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ParenExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ParenExpr.qll
new file mode 100644
index 000000000000..b4b9c48e4cd4
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ParenExpr.qll
@@ -0,0 +1,21 @@
+private import AstImport
+
+class ParenExpr extends Expr, TParenExpr {
+ override string toString() { result = "(...)" }
+
+ Expr getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, parenExprExpr(), result)
+ or
+ not synthChild(r, parenExprExpr(), _) and
+ result = getResultAst(r.(Raw::ParenExpr).getBase())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = parenExprExpr() and
+ result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Pipeline.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Pipeline.qll
new file mode 100644
index 000000000000..9506badacc7d
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Pipeline.qll
@@ -0,0 +1,31 @@
+private import AstImport
+
+class Pipeline extends Expr, TPipeline {
+ override string toString() {
+ if this.getNumberOfComponents() = 1
+ then result = this.getComponent(0).toString()
+ else result = "...|..."
+ }
+
+ Expr getComponent(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = pipelineComp(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::Pipeline).getComponent(i))
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = pipelineComp(index) and
+ result = this.getComponent(index)
+ )
+ }
+
+ Expr getAComponent() { result = this.getComponent(_) }
+
+ int getNumberOfComponents() { result = getRawAst(this).(Raw::Pipeline).getNumberOfComponents() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/PipelineChain.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/PipelineChain.qll
new file mode 100644
index 000000000000..964d5219ae0d
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/PipelineChain.qll
@@ -0,0 +1,31 @@
+private import AstImport
+
+class PipelineChain extends Expr, TPipelineChain {
+ predicate isBackground() { getRawAst(this).(Raw::PipelineChain).isBackground() }
+
+ Expr getLeft() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, pipelineChainLeft(), result)
+ or
+ not synthChild(r, pipelineChainLeft(), _) and
+ result = getResultAst(r.(Raw::PipelineChain).getLeft())
+ )
+ }
+
+ Pipeline getRight() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, pipelineChainRight(), result)
+ or
+ not synthChild(r, pipelineChainRight(), _) and
+ result = getResultAst(r.(Raw::PipelineChain).getRight())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = pipelineChainLeft() and result = this.getLeft()
+ or
+ i = pipelineChainRight() and result = this.getRight()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/PropertyMember.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/PropertyMember.qll
new file mode 100644
index 000000000000..29dac5861aca
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/PropertyMember.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class PropertyMember extends Member, TPropertyMember {
+ final override string getName() { result = getRawAst(this).(Raw::PropertyMember).getName() }
+
+ final override string toString() { result = this.getName() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayExpression.qll
new file mode 100644
index 000000000000..d89c502823a3
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayExpression.qll
@@ -0,0 +1,11 @@
+private import Raw
+
+class ArrayExpr extends @array_expression, Expr {
+ override SourceLocation getLocation() { array_expression_location(this, result) }
+
+ StmtBlock getStmtBlock() { array_expression(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = ArrayExprStmtBlock() and result = this.getStmtBlock()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ArrayLiteral.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayLiteral.qll
similarity index 61%
rename from powershell/ql/lib/semmle/code/powershell/ArrayLiteral.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayLiteral.qll
index 447d26b45e36..1fe24b69d17c 100644
--- a/powershell/ql/lib/semmle/code/powershell/ArrayLiteral.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ArrayLiteral.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class ArrayLiteral extends @array_literal, Expr {
override SourceLocation getLocation() { array_literal_location(this, result) }
@@ -7,5 +7,10 @@ class ArrayLiteral extends @array_literal, Expr {
Expr getAnElement() { array_literal_element(this, _, result) }
- override string toString() { result = "...,..." }
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = ArrayLiteralExpr(index) and
+ result = this.getElement(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/AssignmentStatement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AssignmentStatement.qll
similarity index 61%
rename from powershell/ql/lib/semmle/code/powershell/AssignmentStatement.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AssignmentStatement.qll
index 10bfaed20661..99ff19ccf4bc 100644
--- a/powershell/ql/lib/semmle/code/powershell/AssignmentStatement.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AssignmentStatement.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class AssignStmt extends @assignment_statement, PipelineBase {
override SourceLocation getLocation() { assignment_statement_location(this, result) }
@@ -9,5 +9,11 @@ class AssignStmt extends @assignment_statement, PipelineBase {
Stmt getRightHandSide() { assignment_statement(this, _, _, result) }
- override string toString() { result = "...=..." }
+ final override Ast getChild(ChildIndex i) {
+ i = AssignStmtLeftHandSide() and
+ result = this.getLeftHandSide()
+ or
+ i = AssignStmtRightHandSide() and
+ result = this.getRightHandSide()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Ast.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Ast.qll
new file mode 100644
index 000000000000..5bfb2383a69b
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Ast.qll
@@ -0,0 +1,17 @@
+private import Raw
+import Location
+private import Scope
+
+class Ast extends @ast {
+ final string toString() { none() }
+
+ final Ast getParent() { result.getAChild() = this }
+
+ Ast getChild(ChildIndex i) { none() }
+
+ final Ast getAChild() { result = this.getChild(_) }
+
+ Location getLocation() { none() }
+
+ Scope getScope() { result = scopeOf(this) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/Attribute.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Attribute.qll
similarity index 75%
rename from powershell/ql/lib/semmle/code/powershell/Attribute.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Attribute.qll
index 72a061c09f2a..10c1183bec0a 100644
--- a/powershell/ql/lib/semmle/code/powershell/Attribute.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Attribute.qll
@@ -1,8 +1,6 @@
-import powershell
+private import Raw
class Attribute extends @attribute, AttributeBase {
- override string toString() { result = this.getName() }
-
override SourceLocation getLocation() { attribute_location(this, result) }
string getName() { attribute(this, result, _, _) }
@@ -13,6 +11,16 @@ class Attribute extends @attribute, AttributeBase {
NamedAttributeArgument getNamedArgument(int i) { attribute_named_argument(this, i, result) }
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = AttributeNamedArg(index) and
+ result = this.getNamedArgument(index)
+ or
+ i = AttributePosArg(index) and
+ result = this.getPositionalArgument(index)
+ )
+ }
+
NamedAttributeArgument getANamedArgument() { result = this.getNamedArgument(_) }
int getNumberOfArguments() { result = count(this.getAPositionalArgument()) }
diff --git a/powershell/ql/lib/semmle/code/powershell/AttributeBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributeBase.qll
similarity index 73%
rename from powershell/ql/lib/semmle/code/powershell/AttributeBase.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributeBase.qll
index a0a5a36cdb10..6c4bf907c0a1 100644
--- a/powershell/ql/lib/semmle/code/powershell/AttributeBase.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributeBase.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class AttributeBase extends @attribute_base, Ast { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExpr.qll
new file mode 100644
index 000000000000..8987fd203e69
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExpr.qll
@@ -0,0 +1,17 @@
+private import Raw
+
+class AttributedExpr extends AttributedExprBase, @attributed_expression {
+ final override Expr getExpr() { attributed_expression(this, _, result) }
+
+ final override Attribute getAttribute() { attributed_expression(this, result, _) }
+
+ override Location getLocation() { attributed_expression_location(this, result) }
+
+ override Ast getChild(ChildIndex i) {
+ i = AttributedExprExpr() and
+ result = this.getExpr()
+ or
+ i = AttributedExprAttr() and
+ result = this.getAttribute()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExprBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExprBase.qll
new file mode 100644
index 000000000000..f8eb16d2768b
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/AttributedExprBase.qll
@@ -0,0 +1,7 @@
+private import Raw
+
+class AttributedExprBase extends @attributed_expression_ast, Expr {
+ Expr getExpr() { none() }
+
+ AttributeBase getAttribute() { none() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/BaseConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BaseConstantExpression.qll
similarity index 64%
rename from powershell/ql/lib/semmle/code/powershell/BaseConstantExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BaseConstantExpression.qll
index c495e5da1859..7592f4dfc956 100644
--- a/powershell/ql/lib/semmle/code/powershell/BaseConstantExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BaseConstantExpression.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
/** The base class for constant expressions. */
class BaseConstExpr extends @base_constant_expression, Expr {
@@ -7,7 +7,4 @@ class BaseConstExpr extends @base_constant_expression, Expr {
/** Gets a string literal of this constant expression. */
StringLiteral getValue() { none() }
-
- /** Gets a string literal representing this constant expression. */
- final override string toString() { result = this.getValue().toString() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BinaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BinaryExpression.qll
new file mode 100644
index 000000000000..8c26d6394219
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BinaryExpression.qll
@@ -0,0 +1,35 @@
+private import Raw
+
+class BinaryExpr extends @binary_expression, Expr {
+ override SourceLocation getLocation() { binary_expression_location(this, result) }
+
+ int getKind() { binary_expression(this, result, _, _) }
+
+ /** Gets an operand of this binary expression. */
+ Expr getAnOperand() {
+ result = this.getLeft()
+ or
+ result = this.getRight()
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ i = BinaryExprLeft() and
+ result = this.getLeft()
+ or
+ i = BinaryExprRight() and
+ result = this.getRight()
+ }
+
+ /** Holds if this binary expression has the operands `e1` and `e2`. */
+ predicate hasOperands(Expr e1, Expr e2) {
+ e1 = this.getLeft() and
+ e2 = this.getRight()
+ or
+ e1 = this.getRight() and
+ e2 = this.getLeft()
+ }
+
+ Expr getLeft() { binary_expression(this, _, result, _) }
+
+ Expr getRight() { binary_expression(this, _, _, result) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/BreakStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BreakStmt.qll
similarity index 66%
rename from powershell/ql/lib/semmle/code/powershell/BreakStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BreakStmt.qll
index abd74f3e682f..2c388b865fe8 100644
--- a/powershell/ql/lib/semmle/code/powershell/BreakStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/BreakStmt.qll
@@ -1,7 +1,5 @@
-import powershell
+import Raw
class BreakStmt extends GotoStmt, @break_statement {
override SourceLocation getLocation() { break_statement_location(this, result) }
-
- override string toString() { result = "break" }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CatchClause.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CatchClause.qll
new file mode 100644
index 000000000000..ee66cefc579c
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CatchClause.qll
@@ -0,0 +1,25 @@
+private import Raw
+
+class CatchClause extends @catch_clause, Ast {
+ override SourceLocation getLocation() { catch_clause_location(this, result) }
+
+ StmtBlock getBody() { catch_clause(this, result, _) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = CatchClauseBody() and
+ result = this.getBody()
+ or
+ exists(int index |
+ i = CatchClauseType(index) and
+ result = this.getCatchType(index)
+ )
+ }
+
+ TypeConstraint getCatchType(int i) { catch_clause_catch_type(this, i, result) }
+
+ int getNumberOfCatchTypes() { result = count(this.getACatchType()) }
+
+ TypeConstraint getACatchType() { result = this.getCatchType(_) }
+
+ predicate isCatchAll() { not exists(this.getACatchType()) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/Chainable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Chainable.qll
similarity index 73%
rename from powershell/ql/lib/semmle/code/powershell/Chainable.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Chainable.qll
index 273ccc48113a..1f5419d8f1f4 100644
--- a/powershell/ql/lib/semmle/code/powershell/Chainable.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Chainable.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class Chainable extends @chainable, PipelineBase { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ChildIndex.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ChildIndex.qll
new file mode 100644
index 000000000000..8da1c5e2fb22
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ChildIndex.qll
@@ -0,0 +1,101 @@
+private import Raw
+
+newtype ChildIndex =
+ ArrayExprStmtBlock() or
+ ArrayLiteralExpr(int i) { exists(any(ArrayLiteral lit).getElement(i)) } or
+ AssignStmtLeftHandSide() or
+ AssignStmtRightHandSide() or
+ AttributeNamedArg(int i) { exists(any(Attribute a).getNamedArgument(i)) } or
+ AttributePosArg(int i) { exists(any(Attribute a).getPositionalArgument(i)) } or
+ AttributedExprExpr() or
+ AttributedExprAttr() or
+ BinaryExprLeft() or
+ BinaryExprRight() or
+ CatchClauseBody() or
+ CatchClauseType(int i) { exists(any(CatchClause c).getCatchType(i)) } or
+ CmdElement_(int i) { exists(any(Cmd cmd).getElement(i)) } or // TODO: Get rid of this?
+ CmdCallee() or
+ CmdRedirection(int i) { exists(any(Cmd cmd).getRedirection(i)) } or
+ CmdExprExpr() or
+ ConfigurationName() or
+ ConfigurationBody() or
+ ConvertExprExpr() or
+ ConvertExprType() or
+ ConvertExprAttr() or
+ DataStmtBody() or
+ DataStmtCmdAllowed(int i) { exists(any(DataStmt d).getCmdAllowed(i)) } or
+ DoUntilStmtCond() or
+ DoUntilStmtBody() or
+ DoWhileStmtCond() or
+ DoWhileStmtBody() or
+ DynamicStmtName() or
+ DynamicStmtBody() or
+ ExitStmtPipeline() or
+ ExpandableStringExprExpr(int i) { exists(any(ExpandableStringExpr e).getExpr(i)) } or
+ ForEachStmtVar() or
+ ForEachStmtIter() or
+ ForEachStmtBody() or
+ ForStmtInit() or
+ ForStmtCond() or
+ ForStmtIter() or
+ ForStmtBody() or
+ FunDefStmtBody() or
+ FunDefStmtParam(int i) { exists(any(FunctionDefinitionStmt def).getParameter(i)) } or
+ GotoStmtLabel() or
+ HashTableExprKey(int i) { exists(any(HashTableExpr e).getKey(i)) } or
+ HashTableExprStmt(int i) { exists(any(HashTableExpr e).getStmt(i)) } or
+ IfStmtElse() or
+ IfStmtCond(int i) { exists(any(IfStmt ifstmt).getCondition(i)) } or
+ IfStmtThen(int i) { exists(any(IfStmt ifstmt).getThen(i)) } or
+ IndexExprIndex() or
+ IndexExprBase() or
+ InvokeMemberExprQual() or
+ InvokeMemberExprCallee() or
+ InvokeMemberExprArg(int i) { exists(any(InvokeMemberExpr e).getArgument(i)) } or
+ MemberExprQual() or
+ MemberExprMember() or
+ NamedAttributeArgVal() or
+ MemberAttr(int i) { exists(any(Member m).getAttribute(i)) } or
+ MemberTypeConstraint() or
+ NamedBlockStmt(int i) { exists(any(NamedBlock b).getStmt(i)) } or
+ NamedBlockTrap(int i) { exists(any(NamedBlock b).getTrap(i)) } or
+ ParamBlockAttr(int i) { exists(any(ParamBlock p).getAttribute(i)) } or
+ ParamBlockParam(int i) { exists(any(ParamBlock p).getParameter(i)) } or
+ ParamAttr(int i) { exists(any(Parameter p).getAttribute(i)) } or
+ ParamDefaultVal() or
+ ParenExprExpr() or
+ PipelineComp(int i) { exists(any(Pipeline p).getComponent(i)) } or
+ PipelineChainLeft() or
+ PipelineChainRight() or
+ ReturnStmtPipeline() or
+ RedirectionExpr() or
+ ScriptBlockUsing(int i) { exists(any(ScriptBlock s).getUsing(i)) } or
+ ScriptBlockParamBlock() or
+ ScriptBlockBeginBlock() or
+ ScriptBlockCleanBlock() or
+ ScriptBlockDynParamBlock() or
+ ScriptBlockEndBlock() or
+ ScriptBlockProcessBlock() or
+ ScriptBlockExprBody() or
+ StmtBlockStmt(int i) { exists(any(StmtBlock b).getStmt(i)) } or
+ StmtBlockTrapStmt(int i) { exists(any(StmtBlock b).getTrapStmt(i)) } or
+ ExpandableSubExprExpr() or
+ SwitchStmtCond() or
+ SwitchStmtDefault() or
+ SwitchStmtCase(int i) { exists(any(SwitchStmt s).getCase(i)) } or
+ SwitchStmtPat(int i) { exists(any(SwitchStmt s).getPattern(i)) } or
+ CondExprCond() or
+ CondExprTrue() or
+ CondExprFalse() or
+ ThrowStmtPipeline() or
+ TryStmtBody() or
+ TryStmtCatchClause(int i) { exists(any(TryStmt t).getCatchClause(i)) } or
+ TryStmtFinally() or
+ TypeStmtMember(int i) { exists(any(TypeStmt t).getMember(i)) } or
+ TypeStmtBaseType(int i) { exists(any(TypeStmt t).getBaseType(i)) } or
+ TrapStmtBody() or
+ TrapStmtTypeConstraint() or
+ UnaryExprOp() or
+ UsingExprExpr() or
+ WhileStmtCond() or
+ WhileStmtBody()
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Command.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Command.qll
new file mode 100644
index 000000000000..7186de94065c
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Command.qll
@@ -0,0 +1,105 @@
+private import Raw
+
+private predicate parseCommandName(Cmd cmd, string namespace, string name) {
+ exists(string qualified | command(cmd, qualified, _, _, _) |
+ namespace = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 1) and
+ name = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 2)
+ or
+ // Not a qualified name
+ not exists(qualified.indexOf("\\")) and
+ namespace = "" and
+ name = qualified
+ )
+}
+
+/** A call to a command. */
+class Cmd extends @command, CmdBase {
+ override SourceLocation getLocation() { command_location(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = CmdElement_(index) and
+ result = this.getElement(index)
+ or
+ i = CmdRedirection(index) and
+ result = this.getRedirection(index)
+ )
+ }
+
+ // TODO: This only make sense for some commands (e.g., not dot-sourcing)
+ CmdElement getCallee() { result = this.getElement(0) }
+
+ /** Gets the name of the command without any qualifiers. */
+ string getCommandName() { parseCommandName(this, _, result) }
+
+ /** Holds if the command is qualified. */
+ predicate isQualified() { parseCommandName(this, any(string s | s != ""), _) }
+
+ /** Gets the (possibly qualified) name of this command. */
+ string getQualifiedCommandName() { command(this, result, _, _, _) }
+
+ int getKind() { command(this, _, result, _, _) }
+
+ int getNumElements() { command(this, _, _, result, _) }
+
+ int getNumRedirection() { command(this, _, _, _, result) }
+
+ CmdElement getElement(int i) { command_command_element(this, i, result) }
+
+ /** Gets the expression that determines the command to invoke. */
+ Expr getCommand() { result = this.getElement(0) }
+
+ Redirection getRedirection(int i) { command_redirection(this, i, result) }
+
+ Redirection getARedirection() { result = this.getRedirection(_) }
+
+ Expr getArgument(int i) {
+ result =
+ rank[i + 1](CmdElement e, Expr r, int j |
+ (
+ // For most commands the 0'th element is the command name ...
+ j > 0
+ or
+ // ... but for certain commands (such as the call operator or the dot-
+ // sourcing operator) the 0'th element is not the command name, but
+ // rather the thing to invoke. These all appear to be commands with
+ // an empty string as the command name.
+ this.getCommandName() = ""
+ ) and
+ e = this.getElement(j) and
+ (
+ not e instanceof CmdParameter and
+ r = e
+ or
+ r = e.(CmdParameter).getExpr()
+ )
+ |
+ r order by j
+ )
+ }
+
+ Expr getNamedArgument(string name) {
+ exists(CmdParameter p, int index |
+ result = this.getArgument(index) and
+ p.getName() = name
+ |
+ p.getExpr() = result
+ or
+ exists(int jndex |
+ not exists(p.getExpr()) and
+ this.getElement(jndex) = p and
+ this.getElement(jndex + 1) = result
+ )
+ )
+ }
+}
+
+/** A call to operator `&`. */
+class CallOperator extends Cmd {
+ CallOperator() { this.getKind() = 28 }
+}
+
+/** A call to the dot-sourcing `.`. */
+class DotSourcingOperator extends Cmd {
+ DotSourcingOperator() { this.getKind() = 35 }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/CommandBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandBase.qll
similarity index 73%
rename from powershell/ql/lib/semmle/code/powershell/CommandBase.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandBase.qll
index 2ca1342a826f..b6ba3abb738a 100644
--- a/powershell/ql/lib/semmle/code/powershell/CommandBase.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandBase.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class CmdBase extends @command_base, Chainable { }
diff --git a/powershell/ql/lib/semmle/code/powershell/CommandElement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandElement.qll
similarity index 73%
rename from powershell/ql/lib/semmle/code/powershell/CommandElement.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandElement.qll
index 6dbdffa72503..ffeccacd5ebf 100644
--- a/powershell/ql/lib/semmle/code/powershell/CommandElement.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandElement.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class CmdElement extends @command_element, Ast { }
diff --git a/powershell/ql/lib/semmle/code/powershell/CommandExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandExpression.qll
similarity index 77%
rename from powershell/ql/lib/semmle/code/powershell/CommandExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandExpression.qll
index b8e4bdf29860..7c9343ee7854 100644
--- a/powershell/ql/lib/semmle/code/powershell/CommandExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandExpression.qll
@@ -1,15 +1,18 @@
-import powershell
+private import Raw
class CmdExpr extends @command_expression, CmdBase {
override SourceLocation getLocation() { command_expression_location(this, result) }
Expr getExpr() { command_expression(this, result, _) }
+ final override Ast getChild(ChildIndex i) {
+ i = CmdExprExpr() and
+ result = this.getExpr()
+ }
+
int getNumRedirections() { command_expression(this, _, result) }
Redirection getRedirection(int i) { command_expression_redirection(this, i, result) }
Redirection getARedirection() { result = this.getRedirection(_) }
-
- override string toString() { result = this.getExpr().toString() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandParameter.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandParameter.qll
new file mode 100644
index 000000000000..5a9865830bdf
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommandParameter.qll
@@ -0,0 +1,13 @@
+private import Raw
+
+class CmdParameter extends @command_parameter, CmdElement {
+ override SourceLocation getLocation() { command_parameter_location(this, result) }
+
+ string getName() { command_parameter(this, result) }
+
+ Ast getExpr() {
+ command_parameter_argument(this, result)
+ }
+
+ Cmd getCmd() { result.getElement(_) = this }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/CommentEntity.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommentEntity.qll
similarity index 96%
rename from powershell/ql/lib/semmle/code/powershell/CommentEntity.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommentEntity.qll
index d234eb0f3c78..e270595a12c4 100644
--- a/powershell/ql/lib/semmle/code/powershell/CommentEntity.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/CommentEntity.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class Comment extends @comment_entity {
Location getLocation() { comment_entity_location(this, result) }
diff --git a/powershell/ql/lib/semmle/code/powershell/Configuration.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Configuration.qll
similarity index 69%
rename from powershell/ql/lib/semmle/code/powershell/Configuration.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Configuration.qll
index acc265924a20..8d9461b3c4de 100644
--- a/powershell/ql/lib/semmle/code/powershell/Configuration.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Configuration.qll
@@ -1,14 +1,20 @@
-import powershell
+private import Raw
class Configuration extends @configuration_definition, Stmt {
override SourceLocation getLocation() { configuration_definition_location(this, result) }
- override string toString() { result = "Configuration" }
-
Expr getName() { configuration_definition(this, _, _, result) }
ScriptBlockExpr getBody() { configuration_definition(this, result, _, _) }
+ final override Ast getChild(ChildIndex i) {
+ i = ConfigurationName() and
+ result = this.getName()
+ or
+ i = ConfigurationBody() and
+ result = this.getBody()
+ }
+
predicate isMeta() { configuration_definition(this, _, 1, _) }
predicate isResource() { configuration_definition(this, _, 0, _) }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConstantExpression.qll
new file mode 100644
index 000000000000..3f276a643885
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConstantExpression.qll
@@ -0,0 +1,9 @@
+private import Raw
+
+class ConstExpr extends @constant_expression, BaseConstExpr {
+ override SourceLocation getLocation() { constant_expression_location(this, result) }
+
+ override string getType() { constant_expression(this, result) }
+
+ override StringLiteral getValue() { constant_expression_value(this, result) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ContinueStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ContinueStmt.qll
similarity index 67%
rename from powershell/ql/lib/semmle/code/powershell/ContinueStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ContinueStmt.qll
index 98fe1ba3fcbb..0140a92c8639 100644
--- a/powershell/ql/lib/semmle/code/powershell/ContinueStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ContinueStmt.qll
@@ -1,7 +1,5 @@
-import powershell
+private import Raw
class ContinueStmt extends GotoStmt, @continue_statement {
override SourceLocation getLocation() { continue_statement_location(this, result) }
-
- override string toString() { result = "continue" }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConvertExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConvertExpr.qll
new file mode 100644
index 000000000000..0bc041740928
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ConvertExpr.qll
@@ -0,0 +1,22 @@
+private import Raw
+
+class ConvertExpr extends @convert_expression, AttributedExprBase {
+ override SourceLocation getLocation() { convert_expression_location(this, result) }
+
+ final override Expr getExpr() { convert_expression(this, _, result, _, _) }
+
+ TypeConstraint getType() { convert_expression(this, _, _, result, _) }
+
+ final override AttributeBase getAttribute() { convert_expression(this, result, _, _, _) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = ConvertExprExpr() and
+ result = this.getExpr()
+ or
+ i = ConvertExprType() and
+ result = this.getType()
+ or
+ i = ConvertExprAttr() and
+ result = this.getAttribute()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/DataStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DataStmt.qll
similarity index 62%
rename from powershell/ql/lib/semmle/code/powershell/DataStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DataStmt.qll
index 205cdfbd862f..c8caa6e6cb7c 100644
--- a/powershell/ql/lib/semmle/code/powershell/DataStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DataStmt.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
class DataStmt extends @data_statement, Stmt {
override SourceLocation getLocation() { data_statement_location(this, result) }
- override string toString() { result = "data {...}" }
-
string getVariableName() { data_statement_variable(this, result) }
Expr getCmdAllowed(int i) { data_statement_commands_allowed(this, i, result) }
@@ -12,4 +10,14 @@ class DataStmt extends @data_statement, Stmt {
Expr getACmdAllowed() { result = this.getCmdAllowed(_) }
StmtBlock getBody() { data_statement(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = DataStmtBody() and
+ result = this.getBody()
+ or
+ exists(int index |
+ i = DataStmtCmdAllowed(index) and
+ result = this.getCmdAllowed(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/DoUntilStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoUntilStmt.qll
similarity index 60%
rename from powershell/ql/lib/semmle/code/powershell/DoUntilStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoUntilStmt.qll
index a226931ec2ba..ef40c5460911 100644
--- a/powershell/ql/lib/semmle/code/powershell/DoUntilStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoUntilStmt.qll
@@ -1,11 +1,17 @@
-import powershell
+private import Raw
class DoUntilStmt extends @do_until_statement, LoopStmt {
override SourceLocation getLocation() { do_until_statement_location(this, result) }
- override string toString() { result = "DoUntil" }
-
PipelineBase getCondition() { do_until_statement_condition(this, result) }
final override StmtBlock getBody() { do_until_statement(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = DoUntilStmtCond() and
+ result = this.getCondition()
+ or
+ i = DoUntilStmtBody() and
+ result = this.getBody()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/DoWhileStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoWhileStmt.qll
similarity index 60%
rename from powershell/ql/lib/semmle/code/powershell/DoWhileStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoWhileStmt.qll
index 8d29567d01de..52909c5830fe 100644
--- a/powershell/ql/lib/semmle/code/powershell/DoWhileStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DoWhileStmt.qll
@@ -1,11 +1,17 @@
-import powershell
+private import Raw
class DoWhileStmt extends @do_while_statement, LoopStmt {
override SourceLocation getLocation() { do_while_statement_location(this, result) }
- override string toString() { result = "DoWhile" }
-
PipelineBase getCondition() { do_while_statement_condition(this, result) }
final override StmtBlock getBody() { do_while_statement(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = DoWhileStmtCond() and
+ result = this.getCondition()
+ or
+ i = DoWhileStmtBody() and
+ result = this.getBody()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DynamicStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DynamicStmt.qll
new file mode 100644
index 000000000000..e6e1d9c010cd
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/DynamicStmt.qll
@@ -0,0 +1,27 @@
+private import Raw
+
+class DynamicStmt extends @dynamic_keyword_statement, Stmt {
+ override SourceLocation getLocation() { dynamic_keyword_statement_location(this, result) }
+
+ CmdElement getName() { dynamic_keyword_statement_command_elements(this, 1, result) }
+
+ ScriptBlockExpr getScriptBlock() { dynamic_keyword_statement_command_elements(this, 2, result) }
+
+ HashTableExpr getHashTableExpr() { dynamic_keyword_statement_command_elements(this, 2, result) }
+
+ predicate hasScriptBlock() { exists(this.getScriptBlock()) }
+
+ predicate hasHashTableExpr() { exists(this.getHashTableExpr()) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = DynamicStmtName() and
+ result = this.getName()
+ or
+ i = DynamicStmtBody() and
+ (
+ result = this.getScriptBlock()
+ or
+ result = this.getHashTableExpr()
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ErrorExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorExpr.qll
similarity index 65%
rename from powershell/ql/lib/semmle/code/powershell/ErrorExpr.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorExpr.qll
index 2816f4390b36..1f8d0d97720f 100644
--- a/powershell/ql/lib/semmle/code/powershell/ErrorExpr.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorExpr.qll
@@ -1,7 +1,5 @@
-import powershell
+private import Raw
class ErrorExpr extends @error_expression, Expr {
final override SourceLocation getLocation() { error_expression_location(this, result) }
-
- final override string toString() { result = "error" }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ErrorStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorStmt.qll
similarity index 66%
rename from powershell/ql/lib/semmle/code/powershell/ErrorStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorStmt.qll
index 13be222c9c11..451922ad7e5c 100644
--- a/powershell/ql/lib/semmle/code/powershell/ErrorStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ErrorStmt.qll
@@ -1,7 +1,5 @@
-import powershell
+private import Raw
class ErrorStmt extends @error_statement, PipelineBase {
final override SourceLocation getLocation() { error_statement_location(this, result) }
-
- final override string toString() { result = "error" }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ExitStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExitStmt.qll
similarity index 69%
rename from powershell/ql/lib/semmle/code/powershell/ExitStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExitStmt.qll
index 421bc453011f..299735945cf3 100644
--- a/powershell/ql/lib/semmle/code/powershell/ExitStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExitStmt.qll
@@ -1,12 +1,14 @@
-import powershell
+private import Raw
class ExitStmt extends @exit_statement, Stmt {
override SourceLocation getLocation() { exit_statement_location(this, result) }
- override string toString() { if this.hasPipeline() then result = "exit ..." else result = "exit" }
-
/** ..., if any. */
PipelineBase getPipeline() { exit_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = ExitStmtPipeline() and result = this.getPipeline()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ExpandableStringExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExpandableStringExpression.qll
similarity index 72%
rename from powershell/ql/lib/semmle/code/powershell/ExpandableStringExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExpandableStringExpression.qll
index fa3a8a77ba25..86b08a5e4121 100644
--- a/powershell/ql/lib/semmle/code/powershell/ExpandableStringExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ExpandableStringExpression.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
class ExpandableStringExpr extends @expandable_string_expression, Expr {
override SourceLocation getLocation() { expandable_string_expression_location(this, result) }
- override string toString() { result = this.getUnexpandedValue().toString() }
-
StringLiteral getUnexpandedValue() { expandable_string_expression(this, result, _, _) }
int getNumExprs() { result = count(this.getAnExpr()) }
@@ -12,4 +10,11 @@ class ExpandableStringExpr extends @expandable_string_expression, Expr {
Expr getExpr(int i) { expandable_string_expression_nested_expression(this, i, result) }
Expr getAnExpr() { result = this.getExpr(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = ExpandableStringExprExpr(index) and
+ result = this.getExpr(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Expression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Expression.qll
new file mode 100644
index 000000000000..930b918c472c
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Expression.qll
@@ -0,0 +1,8 @@
+private import Raw
+
+/**
+ * An expression.
+ *
+ * This is the topmost class in the hierachy of all expression in PowerShell.
+ */
+class Expr extends @expression, CmdElement { }
diff --git a/powershell/ql/lib/semmle/code/powershell/File.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/File.qll
similarity index 100%
rename from powershell/ql/lib/semmle/code/powershell/File.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/File.qll
diff --git a/powershell/ql/lib/semmle/code/powershell/FileRedirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/FileRedirection.qll
similarity index 64%
rename from powershell/ql/lib/semmle/code/powershell/FileRedirection.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/FileRedirection.qll
index 68dca062551f..c398aeb9ec9a 100644
--- a/powershell/ql/lib/semmle/code/powershell/FileRedirection.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/FileRedirection.qll
@@ -1,7 +1,5 @@
-import powershell
+private import Raw
class FileRedirection extends @file_redirection, Redirection {
- override string toString() { result = "FileRedirection" }
-
override Location getLocation() { file_redirection_location(this, result) }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ForEachStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForEachStmt.qll
similarity index 63%
rename from powershell/ql/lib/semmle/code/powershell/ForEachStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForEachStmt.qll
index 4cbcc87038f7..980c2e848949 100644
--- a/powershell/ql/lib/semmle/code/powershell/ForEachStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForEachStmt.qll
@@ -1,23 +1,21 @@
-import powershell
+private import Raw
class ForEachStmt extends @foreach_statement, LoopStmt {
override SourceLocation getLocation() { foreach_statement_location(this, result) }
- override string toString() { result = "forach(... in ...)" }
-
final override StmtBlock getBody() { foreach_statement(this, _, _, result, _) }
VarAccess getVarAccess() { foreach_statement(this, result, _, _, _) }
- Variable getVariable() {
- exists(VarAccess va |
- va = this.getVarAccess() and
- foreach_statement(this, va, _, _, _) and
- result = va.getVariable()
- )
- }
-
PipelineBase getIterableExpr() { foreach_statement(this, _, result, _, _) }
predicate isParallel() { foreach_statement(this, _, _, _, 1) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = ForEachStmtVar() and result = this.getVarAccess()
+ or
+ i = ForEachStmtIter() and result = this.getIterableExpr()
+ or
+ i = ForEachStmtBody() and result = this.getBody()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ForStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForStmt.qll
similarity index 56%
rename from powershell/ql/lib/semmle/code/powershell/ForStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForStmt.qll
index 104d3e3e2272..e136f274b214 100644
--- a/powershell/ql/lib/semmle/code/powershell/ForStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ForStmt.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
class ForStmt extends @for_statement, LoopStmt {
override SourceLocation getLocation() { for_statement_location(this, result) }
- override string toString() { result = "for(...;...;...)" }
-
PipelineBase getInitializer() { for_statement_initializer(this, result) }
PipelineBase getCondition() { for_statement_condition(this, result) }
@@ -12,4 +10,18 @@ class ForStmt extends @for_statement, LoopStmt {
PipelineBase getIterator() { for_statement_iterator(this, result) }
final override StmtBlock getBody() { for_statement(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = ForStmtInit() and
+ result = this.getInitializer()
+ or
+ i = ForStmtCond() and
+ result = this.getCondition()
+ or
+ i = ForStmtIter() and
+ result = this.getIterator()
+ or
+ i = ForStmtBody() and
+ result = this.getBody()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Function.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Function.qll
new file mode 100644
index 000000000000..6b303fb36be5
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Function.qll
@@ -0,0 +1,22 @@
+private import Raw
+
+class FunctionDefinitionStmt extends @function_definition, Stmt {
+ override Location getLocation() { function_definition_location(this, result) }
+
+ ScriptBlock getBody() { function_definition(this, result, _, _, _) }
+
+ string getName() { function_definition(this, _, result, _, _) }
+
+ Parameter getParameter(int i) { function_definition_parameter(this, i, result) }
+
+ Parameter getAParameter() { result = this.getParameter(_) }
+
+ override Ast getChild(ChildIndex i) {
+ i = FunDefStmtBody() and result = this.getBody()
+ or
+ exists(int index |
+ i = FunDefStmtParam(index) and
+ result = this.getParameter(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/GotoStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/GotoStmt.qll
similarity index 59%
rename from powershell/ql/lib/semmle/code/powershell/GotoStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/GotoStmt.qll
index 64cc20bf8002..bae96f4aa51f 100644
--- a/powershell/ql/lib/semmle/code/powershell/GotoStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/GotoStmt.qll
@@ -1,8 +1,9 @@
-import powershell
+private import Raw
/** A `break` or `continue` statement. */
class GotoStmt extends @labelled_statement, Stmt {
-
/** ..., if any. */
Expr getLabel() { statement_label(this, result) }
+
+ final override Ast getChild(ChildIndex i) { i = GotoStmtLabel() and result = this.getLabel() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/HashTable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/HashTable.qll
new file mode 100644
index 000000000000..200c1b13a803
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/HashTable.qll
@@ -0,0 +1,23 @@
+private import Raw
+
+class HashTableExpr extends @hash_table, Expr {
+ final override Location getLocation() { hash_table_location(this, result) }
+
+ Expr getKey(int i) { hash_table_key_value_pairs(this, i, result, _) }
+
+ Expr getAKey() { result = this.getKey(_) }
+
+ Stmt getStmt(int i) { hash_table_key_value_pairs(this, i, _, result) }
+
+ Stmt getAStmt() { result = this.getStmt(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = HashTableExprKey(index) and
+ result = this.getKey(index)
+ or
+ i = HashTableExprStmt(index) and
+ result = this.getStmt(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/IfStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IfStmt.qll
similarity index 66%
rename from powershell/ql/lib/semmle/code/powershell/IfStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IfStmt.qll
index 21ce4d68fc8b..35754f5740a1 100644
--- a/powershell/ql/lib/semmle/code/powershell/IfStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IfStmt.qll
@@ -1,12 +1,8 @@
-import powershell
+private import Raw
class IfStmt extends @if_statement, Stmt {
override SourceLocation getLocation() { if_statement_location(this, result) }
- override string toString() {
- if this.hasElse() then result = "if (...) {...} else {...}" else result = "if (...) {...}"
- }
-
PipelineBase getCondition(int i) { if_statement_clause(this, i, result, _) }
PipelineBase getACondition() { result = this.getCondition(_) }
@@ -21,4 +17,17 @@ class IfStmt extends @if_statement, Stmt {
StmtBlock getElse() { if_statement_else(this, result) }
predicate hasElse() { exists(this.getElse()) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = IfStmtElse() and
+ result = this.getElse()
+ or
+ exists(int index |
+ i = IfStmtCond(index) and
+ result = this.getCondition(index)
+ or
+ i = IfStmtThen(index) and
+ result = this.getThen(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IndexExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IndexExpr.qll
new file mode 100644
index 000000000000..9b98e364480a
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/IndexExpr.qll
@@ -0,0 +1,18 @@
+private import Raw
+
+class IndexExpr extends @index_expression, Expr {
+ override SourceLocation getLocation() { index_expression_location(this, result) }
+
+ Expr getIndex() { index_expression(this, result, _, _) } // TODO: Change @ast to @expr in the dbscheme
+
+ Expr getBase() { index_expression(this, _, result, _) } // TODO: Change @ast to @expr in the dbscheme
+
+ predicate isNullConditional() { index_expression(this, _, _, true) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = IndexExprIndex() and
+ result = this.getIndex()
+ or
+ i = IndexExprBase() and result = this.getBase()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/InvokeMemberExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/InvokeMemberExpression.qll
new file mode 100644
index 000000000000..a2fa623f3957
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/InvokeMemberExpression.qll
@@ -0,0 +1,32 @@
+private import Raw
+
+class InvokeMemberExpr extends @invoke_member_expression, MemberExprBase {
+ override SourceLocation getLocation() { invoke_member_expression_location(this, result) }
+
+ Expr getQualifier() { invoke_member_expression(this, result, _) }
+
+ string getName() { result = this.getCallee().(StringConstExpr).getValue().getValue() }
+
+ Expr getCallee() { invoke_member_expression(this, _, result) }
+
+ string getMemberName() { result = this.getCallee().(StringConstExpr).getValue().getValue() }
+
+ Expr getArgument(int i) { invoke_member_expression_argument(this, i, result) }
+
+ Expr getAnArgument() { invoke_member_expression_argument(this, _, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = InvokeMemberExprQual() and
+ result = this.getQualifier()
+ or
+ i = InvokeMemberExprCallee() and
+ result = this.getCallee()
+ or
+ exists(int index |
+ i = InvokeMemberExprArg(index) and
+ result = this.getArgument(index)
+ )
+ }
+
+ override predicate isStatic() { this.getQualifier() instanceof TypeNameExpr }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/LabeledStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LabeledStmt.qll
similarity index 84%
rename from powershell/ql/lib/semmle/code/powershell/LabeledStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LabeledStmt.qll
index fff4e1712ccb..058d15922dfe 100644
--- a/powershell/ql/lib/semmle/code/powershell/LabeledStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LabeledStmt.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class LabeledStmt extends @labeled_statement, Stmt {
string getLabel() { label(this, result) }
diff --git a/powershell/ql/lib/semmle/code/powershell/Location.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Location.qll
similarity index 84%
rename from powershell/ql/lib/semmle/code/powershell/Location.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Location.qll
index c08dcb83af11..574d5598578f 100644
--- a/powershell/ql/lib/semmle/code/powershell/Location.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Location.qll
@@ -44,6 +44,14 @@ class Location extends @location {
/** Gets the 1-based column number (inclusive) where this location ends. */
int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
+
+ /** Holds if this location starts strictly before the specified location. */
+ pragma[inline]
+ predicate strictlyBefore(Location other) {
+ this.getStartLine() < other.getStartLine()
+ or
+ this.getStartLine() = other.getStartLine() and this.getStartColumn() < other.getStartColumn()
+ }
}
/** An empty location. */
diff --git a/powershell/ql/lib/semmle/code/powershell/LoopStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LoopStmt.qll
similarity index 82%
rename from powershell/ql/lib/semmle/code/powershell/LoopStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LoopStmt.qll
index edd9417a4951..2889b1c7d8d7 100644
--- a/powershell/ql/lib/semmle/code/powershell/LoopStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/LoopStmt.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class LoopStmt extends @loop_statement, LabeledStmt {
StmtBlock getBody() { none() }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Member.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Member.qll
new file mode 100644
index 000000000000..9c0c2d29ba0b
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Member.qll
@@ -0,0 +1,62 @@
+private import Raw
+
+class Member extends @member, Ast {
+ TypeStmt getDeclaringType() { result.getAMember() = this }
+
+ string getName() { none() }
+
+ predicate isHidden() { none() }
+
+ predicate isPrivate() { none() }
+
+ predicate isPublic() { none() }
+
+ predicate isStatic() { none() }
+
+ Attribute getAttribute(int i) { none() }
+
+ final Attribute getAnAttribute() { result = this.getAttribute(_) }
+
+ TypeConstraint getTypeConstraint() { none() }
+
+ override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = MemberAttr(index) and
+ result = this.getAttribute(index)
+ )
+ or
+ i = MemberTypeConstraint() and
+ result = this.getTypeConstraint()
+ }
+}
+
+/**
+ * A method definition. That is, a function defined inside a class definition.
+ */
+class Method extends Member {
+ Method() { function_member(this, _, _, _, _, _, _, _, _) }
+
+ ScriptBlock getBody() { function_member(this, result, _, _, _, _, _, _, _) }
+
+ final override predicate isStatic() { function_member(this, _, _, _, _, _, true, _, _) }
+
+ final override string getName() { function_member(this, _, _, _, _, _, _, result, _) }
+
+ predicate isConstructor() { function_member(this, _, true, _, _, _, _, _, _) }
+
+ override Location getLocation() { function_member_location(this, result) }
+
+ override Attribute getAttribute(int i) { function_member_attribute(this, i, result) }
+
+ override TypeConstraint getTypeConstraint() { function_member_return_type(this, result) }
+
+ FunctionDefinitionStmt getFunctionDefinitionStmt() { result.getBody() = this.getBody() }
+}
+
+class MethodScriptBlock extends ScriptBlock {
+ Method m;
+
+ MethodScriptBlock() { m.getBody() = this }
+
+ Method getMethod() { result = m }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/MemberExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpr.qll
similarity index 82%
rename from powershell/ql/lib/semmle/code/powershell/MemberExpr.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpr.qll
index 1d6d143c053e..26f4996f52ca 100644
--- a/powershell/ql/lib/semmle/code/powershell/MemberExpr.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpr.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class MemberExpr extends @member_expression, MemberExprBase {
final override Location getLocation() { member_expression_location(this, result) }
@@ -14,7 +14,12 @@ class MemberExpr extends @member_expression, MemberExprBase {
override predicate isStatic() { member_expression(this, _, _, _, true) }
- final override string toString() { result = this.getMember().toString() }
+ final override Ast getChild(ChildIndex i) {
+ i = MemberExprQual() and result = this.getQualifier()
+ or
+ i = MemberExprMember() and
+ result = this.getMember()
+ }
}
/** A `MemberExpr` that is being written to. */
diff --git a/powershell/ql/lib/semmle/code/powershell/MemberExpressionBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpressionBase.qll
similarity index 83%
rename from powershell/ql/lib/semmle/code/powershell/MemberExpressionBase.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpressionBase.qll
index 81db24f00196..02758e5a7867 100644
--- a/powershell/ql/lib/semmle/code/powershell/MemberExpressionBase.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MemberExpressionBase.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class MemberExprBase extends @member_expression_base, Expr {
predicate isStatic() { none() }
diff --git a/powershell/ql/lib/semmle/code/powershell/MergingRedirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MergingRedirection.qll
similarity index 65%
rename from powershell/ql/lib/semmle/code/powershell/MergingRedirection.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MergingRedirection.qll
index b227fc3c585f..491dbada6bb0 100644
--- a/powershell/ql/lib/semmle/code/powershell/MergingRedirection.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/MergingRedirection.qll
@@ -1,7 +1,5 @@
-import powershell
+private import Raw
class MergingRedirection extends @merging_redirection, Redirection {
- override string toString() { result = "MergingRedirection" }
-
override Location getLocation() { merging_redirection_location(this, result) }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ModuleSpecification.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ModuleSpecification.qll
similarity index 96%
rename from powershell/ql/lib/semmle/code/powershell/ModuleSpecification.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ModuleSpecification.qll
index 5e2a3d3d3918..9a512d62690c 100644
--- a/powershell/ql/lib/semmle/code/powershell/ModuleSpecification.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ModuleSpecification.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class ModuleSpecification extends @module_specification {
string toString() { result = this.getName() }
diff --git a/powershell/ql/lib/semmle/code/powershell/NamedAttributeArgument.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedAttributeArgument.qll
similarity index 83%
rename from powershell/ql/lib/semmle/code/powershell/NamedAttributeArgument.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedAttributeArgument.qll
index 1d05343b87ea..324dec4d27e7 100644
--- a/powershell/ql/lib/semmle/code/powershell/NamedAttributeArgument.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedAttributeArgument.qll
@@ -1,8 +1,6 @@
-import powershell
+private import Raw
class NamedAttributeArgument extends @named_attribute_argument, Ast {
- final override string toString() { result = this.getName() }
-
final override SourceLocation getLocation() { named_attribute_argument_location(this, result) }
string getName() { named_attribute_argument(this, result, _) }
@@ -10,6 +8,10 @@ class NamedAttributeArgument extends @named_attribute_argument, Ast {
predicate hasName(string s) { this.getName() = s }
Expr getValue() { named_attribute_argument(this, _, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = NamedAttributeArgVal() and result = this.getValue()
+ }
}
class ValueFromPipelineAttribute extends NamedAttributeArgument {
diff --git a/powershell/ql/lib/semmle/code/powershell/NamedBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedBlock.qll
similarity index 50%
rename from powershell/ql/lib/semmle/code/powershell/NamedBlock.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedBlock.qll
index 5bf4de25cb38..f11e621e74d0 100644
--- a/powershell/ql/lib/semmle/code/powershell/NamedBlock.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/NamedBlock.qll
@@ -1,8 +1,6 @@
-import powershell
+private import Raw
class NamedBlock extends @named_block, Ast {
- override string toString() { result = "{...}" }
-
override SourceLocation getLocation() { named_block_location(this, result) }
int getNumStatements() { named_block(this, result, _) }
@@ -16,4 +14,23 @@ class NamedBlock extends @named_block, Ast {
TrapStmt getTrap(int i) { named_block_trap(this, i, result) }
TrapStmt getATrap() { result = this.getTrap(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = NamedBlockStmt(index) and
+ result = this.getStmt(index)
+ or
+ i = NamedBlockTrap(index) and
+ result = this.getTrap(index)
+ )
+ }
+}
+
+/** A `process` block. */
+class ProcessBlock extends NamedBlock {
+ ScriptBlock scriptBlock;
+
+ ProcessBlock() { scriptBlock.getProcessBlock() = this }
+
+ ScriptBlock getScriptBlock() { result = scriptBlock }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParamBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParamBlock.qll
new file mode 100644
index 000000000000..0ebae92854af
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParamBlock.qll
@@ -0,0 +1,36 @@
+private import Raw
+
+class ParamBlock extends @param_block, Ast {
+ override SourceLocation getLocation() { param_block_location(this, result) }
+
+ int getNumAttributes() { param_block(this, result, _) }
+
+ int getNumParameters() { param_block(this, _, result) }
+
+ Attribute getAttribute(int i) { param_block_attribute(this, i, result) }
+
+ Attribute getAnAttribute() { result = this.getAttribute(_) }
+
+ Parameter getParameter(int i) { param_block_parameter(this, i, result) }
+
+ Parameter getAParameter() { result = this.getParameter(_) }
+
+ PipelineParameter getPipelineParameter() { result = this.getAParameter() }
+
+ PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
+ result = this.getAParameter()
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = ParamBlockAttr(index) and
+ result = this.getAttribute(index)
+ or
+ i = ParamBlockParam(index) and
+ result = this.getParameter(index)
+ )
+ }
+
+ /** Gets the script block, if any. */
+ ScriptBlock getScriptBlock() { result.getParamBlock() = this }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Parameter.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Parameter.qll
new file mode 100644
index 000000000000..32669d0141ea
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Parameter.qll
@@ -0,0 +1,60 @@
+private import Raw
+
+class Parameter extends @parameter, Ast {
+ string getName() {
+ exists(@variable_expression va |
+ parameter(this, va, _, _) and
+ variable_expression(va, result, _, _, _, _, _, _, _, _, _, _)
+ )
+ }
+
+ override SourceLocation getLocation() { parameter_location(this, result) }
+
+ AttributeBase getAttribute(int i) { parameter_attribute(this, i, result) }
+
+ AttributeBase getAnAttribute() { result = this.getAttribute(_) }
+
+ Expr getDefaultValue() { parameter_default_value(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = ParamAttr(index) and
+ result = this.getAttribute(index)
+ )
+ or
+ i = ParamDefaultVal() and
+ result = this.getDefaultValue()
+ }
+
+ string getStaticType() { parameter(this, _, result, _) }
+}
+
+class PipelineParameter extends Parameter {
+ PipelineParameter() {
+ exists(NamedAttributeArgument namedAttribute |
+ this.getAnAttribute().(Attribute).getANamedArgument() = namedAttribute and
+ namedAttribute.getName().toLowerCase() = "valuefrompipeline"
+ |
+ namedAttribute.getValue().(ConstExpr).getValue().getValue() = "true"
+ or
+ not exists(namedAttribute.getValue().(ConstExpr).getValue().getValue())
+ )
+ }
+
+ ScriptBlock getScriptBlock() { result.getParamBlock().getAParameter() = this }
+}
+
+class PipelineByPropertyNameParameter extends Parameter {
+ PipelineByPropertyNameParameter() {
+ exists(NamedAttributeArgument namedAttribute |
+ this.getAnAttribute().(Attribute).getANamedArgument() = namedAttribute and
+ namedAttribute.getName().toLowerCase() = "valuefrompipelinebypropertyname"
+ |
+ namedAttribute.getValue().(ConstExpr).getValue().getValue() = "true"
+ or
+ not exists(namedAttribute.getValue().(ConstExpr).getValue().getValue())
+ )
+ }
+
+ ScriptBlock getScriptBlock() { result.getParamBlock().getAParameter() = this }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ParenExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParenExpression.qll
similarity index 63%
rename from powershell/ql/lib/semmle/code/powershell/ParenExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParenExpression.qll
index 6a71d2681307..5e767329b165 100644
--- a/powershell/ql/lib/semmle/code/powershell/ParenExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ParenExpression.qll
@@ -1,9 +1,9 @@
-import powershell
+private import Raw
class ParenExpr extends @paren_expression, Expr {
PipelineBase getBase() { paren_expression(this, result) }
override SourceLocation getLocation() { paren_expression_location(this, result) }
- override string toString() { result = "(...)" }
+ final override Ast getChild(ChildIndex i) { i = ParenExprExpr() and result = this.getBase() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/Pipeline.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Pipeline.qll
similarity index 66%
rename from powershell/ql/lib/semmle/code/powershell/Pipeline.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Pipeline.qll
index f630a117e547..c8d24d6f8ba6 100644
--- a/powershell/ql/lib/semmle/code/powershell/Pipeline.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Pipeline.qll
@@ -1,12 +1,6 @@
-import powershell
+private import Raw
class Pipeline extends @pipeline, Chainable {
- override string toString() {
- if this.getNumberOfComponents() = 1
- then result = this.getComponent(0).toString()
- else result = "...|..."
- }
-
override SourceLocation getLocation() { pipeline_location(this, result) }
int getNumberOfComponents() { result = count(this.getAComponent()) }
@@ -14,4 +8,11 @@ class Pipeline extends @pipeline, Chainable {
CmdBase getComponent(int i) { pipeline_component(this, i, result) }
CmdBase getAComponent() { result = this.getComponent(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = PipelineComp(index) and
+ result = this.getComponent(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/PipelineBase.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineBase.qll
similarity index 73%
rename from powershell/ql/lib/semmle/code/powershell/PipelineBase.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineBase.qll
index bb2d8cab85e4..9c1e793a4e5c 100644
--- a/powershell/ql/lib/semmle/code/powershell/PipelineBase.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineBase.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class PipelineBase extends @pipeline_base, Stmt { }
diff --git a/powershell/ql/lib/semmle/code/powershell/PipelineChain.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineChain.qll
similarity index 64%
rename from powershell/ql/lib/semmle/code/powershell/PipelineChain.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineChain.qll
index ee5dd56cec0a..f7e08c9b41e5 100644
--- a/powershell/ql/lib/semmle/code/powershell/PipelineChain.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PipelineChain.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class PipelineChain extends @pipeline_chain, Chainable {
final override SourceLocation getLocation() { pipeline_chain_location(this, result) }
@@ -8,4 +8,10 @@ class PipelineChain extends @pipeline_chain, Chainable {
Chainable getLeft() { pipeline_chain(this, _, _, result, _) }
Pipeline getRight() { pipeline_chain(this, _, _, _, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = PipelineChainLeft() and result = this.getLeft()
+ or
+ i = PipelineChainRight() and result = this.getRight()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/PropertyMember.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PropertyMember.qll
similarity index 72%
rename from powershell/ql/lib/semmle/code/powershell/PropertyMember.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PropertyMember.qll
index e9144dc78e45..b7830927ed9a 100644
--- a/powershell/ql/lib/semmle/code/powershell/PropertyMember.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/PropertyMember.qll
@@ -1,12 +1,10 @@
-import powershell
+private import Raw
class PropertyMember extends @property_member, Member {
override string getName() { property_member(this, _, _, _, _, result, _) }
override SourceLocation getLocation() { property_member_location(this, result) }
- override string toString() { result = this.getName() }
-
override predicate isHidden() { property_member(this, true, _, _, _, _, _) }
override predicate isPrivate() { property_member(this, _, true, _, _, _, _) }
@@ -14,4 +12,8 @@ class PropertyMember extends @property_member, Member {
override predicate isPublic() { property_member(this, _, _, true, _, _, _) }
override predicate isStatic() { property_member(this, _, _, _, true, _, _) }
+
+ override Attribute getAttribute(int i) { property_member_attribute(this, i, result) }
+
+ override TypeConstraint getTypeConstraint() { property_member_property_type(this, result) }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Raw.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Raw.qll
new file mode 100644
index 000000000000..537161ac3111
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Raw.qll
@@ -0,0 +1,84 @@
+import ChildIndex
+import ArrayExpression
+import ArrayLiteral
+import AssignmentStatement
+import Ast
+import Attribute
+import AttributeBase
+import BaseConstantExpression
+import BinaryExpression
+import BreakStmt
+import CatchClause
+import Chainable
+import Command
+import CommandBase
+import CommandElement
+import CommandExpression
+import CommandParameter
+import CommentEntity
+import Configuration
+import ConstantExpression
+import ContinueStmt
+import ConvertExpr
+import DataStmt
+import DoUntilStmt
+import DoWhileStmt
+import DynamicStmt
+import ErrorExpr
+import ErrorStmt
+import ExitStmt
+import ExpandableStringExpression
+import Expression
+import File
+import FileRedirection
+import ForEachStmt
+import ForStmt
+import Function
+import GotoStmt
+import HashTable
+import IfStmt
+import IndexExpr
+import InvokeMemberExpression
+import LabeledStmt
+import Location
+import LoopStmt
+import Member
+import MemberExpr
+import MemberExpressionBase
+import MergingRedirection
+import ModuleSpecification
+import NamedAttributeArgument
+import NamedBlock
+import ParamBlock
+import Parameter
+import ParenExpression
+import Pipeline
+import PipelineBase
+import PipelineChain
+import PropertyMember
+import Redirection
+import ReturnStmt
+import ScriptBlock
+import ScriptBlockExpr
+import SourceLocation
+import Statement
+import StatementBlock
+import StringConstantExpression
+import StringLiteral
+import SubExpression
+import SwitchStmt
+import TernaryExpression
+import ThrowStmt
+import TrapStatement
+import TryStmt
+import Type
+import TypeConstraint
+import TypeExpression
+import UnaryExpression
+import UsingExpression
+import UsingStmt
+import VariableExpression
+import WhileStmt
+import AttributedExpr
+import AttributedExprBase
+import Scope
\ No newline at end of file
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Redirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Redirection.qll
new file mode 100644
index 000000000000..e4303171df3f
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Redirection.qll
@@ -0,0 +1,10 @@
+private import Raw
+
+class Redirection extends @redirection, Ast {
+ Expr getExpr() { parent(result, this) } // TODO: Is there really no other way to get this?
+
+ final override Ast getChild(ChildIndex i) {
+ i = RedirectionExpr() and
+ result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ReturnStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ReturnStmt.qll
similarity index 67%
rename from powershell/ql/lib/semmle/code/powershell/ReturnStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ReturnStmt.qll
index aa8ad6732514..a007dec2ffec 100644
--- a/powershell/ql/lib/semmle/code/powershell/ReturnStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ReturnStmt.qll
@@ -1,13 +1,11 @@
-import powershell
+private import Raw
class ReturnStmt extends @return_statement, Stmt {
override SourceLocation getLocation() { return_statement_location(this, result) }
- override string toString() {
- if this.hasPipeline() then result = "return ..." else result = "return"
- }
-
PipelineBase getPipeline() { return_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
+
+ final override Ast getChild(ChildIndex i) { i = ReturnStmtPipeline() and result = this.getPipeline() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Scope.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Scope.qll
new file mode 100644
index 000000000000..6c8488e1a1a8
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Scope.qll
@@ -0,0 +1,59 @@
+private import Raw
+
+/** Gets the enclosing scope of `n`. */
+Scope scopeOf(Ast n) {
+ exists(Ast m | m = n.getParent() |
+ m = result
+ or
+ not m instanceof Scope and result = scopeOf(m)
+ )
+}
+
+module Parameter {
+ abstract class Scope extends Ast {
+ abstract string getName();
+ }
+
+ private class ParameterScope extends Scope instanceof Parameter {
+ final override string getName() { result = Parameter.super.getName() }
+ }
+}
+
+abstract private class ScopeImpl extends Ast {
+ abstract Scope getOuterScopeImpl();
+
+ abstract Ast getParameterImpl(int index);
+}
+
+class Scope instanceof ScopeImpl {
+ Scope getOuterScope() { result = super.getOuterScopeImpl() }
+
+ string toString() { result = super.toString() }
+
+ Parameter getParameter(int index) { result = super.getParameterImpl(index) }
+
+ Parameter getAParameter() { result = this.getParameter(_) }
+
+ Location getLocation() { result = super.getLocation() }
+}
+
+/**
+ * A variable scope. This is either a top-level (file), a module, a class,
+ * or a callable.
+ */
+private class ScriptBlockScope extends ScopeImpl instanceof ScriptBlock {
+ /** Gets the outer scope, if any. */
+ override Scope getOuterScopeImpl() { result = scopeOf(this) }
+
+ override Parameter getParameterImpl(int index) {
+ exists(ParamBlock pb |
+ pb.getParameter(index) = result and
+ pb.getScriptBlock() = this
+ )
+ or
+ exists(FunctionDefinitionStmt func |
+ func.getParameter(index) = result and
+ func.getBody() = this
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ScriptBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlock.qll
similarity index 50%
rename from powershell/ql/lib/semmle/code/powershell/ScriptBlock.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlock.qll
index 4e6c77352234..4b923136aa38 100644
--- a/powershell/ql/lib/semmle/code/powershell/ScriptBlock.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlock.qll
@@ -1,15 +1,8 @@
-import powershell
-private import semmle.code.powershell.controlflow.internal.Scope
+private import Raw
class ScriptBlock extends @script_block, Ast {
predicate isTopLevel() { not exists(this.getParent()) }
- override string toString() {
- if this.isTopLevel()
- then result = this.getLocation().getFile().getBaseName()
- else result = "{...}"
- }
-
override Location getLocation() { script_block_location(this, result) }
int getNumUsings() { script_block(this, result, _, _, _, _) }
@@ -50,59 +43,29 @@ class ScriptBlock extends @script_block, Ast {
ModuleSpecification getAModuleSpecification() { result = this.getModuleSpecification(_) }
- final override Scope getEnclosingScope() { result = this }
-
- /**
- * Gets the `i`'th paramter in this scope.
- *
- * This may be both function paramters and parameter block parameters.
- */
- Parameter getParameter(int i) {
- exists(Function func |
- func.getBody() = this and
- result = func.getParameter(i)
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = ScriptBlockUsing(index) and
+ result = this.getUsing(index)
)
or
- this.isTopLevel() and
- result = this.getParamBlock().getParameter(i)
- }
-
- /**
- * Gets a paramter in this scope.
- *
- * This may be both function parameters and parameter block parameters.
- */
- Parameter getAParameter() { result = this.getParameter(_) }
-
- Parameter getThisParameter() {
- exists(Function func |
- func.getBody() = this and
- result = func.getThisParameter()
- )
- }
-
- /** Gets the number of function parameters. */
- final int getNumberOfParameters() { result = count(this.getAParameter()) }
-
- final Parameter getParameterExcludingPiplines(int i) {
- result = this.getParamBlock().getParameterExcludingPiplines(i)
- }
-}
-
-/** A `process` block. */
-class ProcessBlock extends NamedBlock {
- ScriptBlock scriptBlock;
-
- ProcessBlock() { scriptBlock.getProcessBlock() = this }
-
- ScriptBlock getScriptBlock() { result = scriptBlock }
-
- PipelineParameter getPipelineParameter() {
- result = scriptBlock.getEnclosingFunction().getAParameter()
- }
-
- PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
- result = scriptBlock.getEnclosingFunction().getAParameter()
+ i = ScriptBlockParamBlock() and
+ result = this.getParamBlock()
+ or
+ i = ScriptBlockBeginBlock() and
+ result = this.getBeginBlock()
+ or
+ i = ScriptBlockCleanBlock() and
+ result = this.getCleanBlock()
+ or
+ i = ScriptBlockDynParamBlock() and
+ result = this.getDynamicParamBlock()
+ or
+ i = ScriptBlockEndBlock() and
+ result = this.getEndBlock()
+ or
+ i = ScriptBlockProcessBlock() and
+ result = this.getProcessBlock()
}
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ScriptBlockExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlockExpr.qll
similarity index 65%
rename from powershell/ql/lib/semmle/code/powershell/ScriptBlockExpr.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlockExpr.qll
index 78dd5abbc2e6..288daed9b0ee 100644
--- a/powershell/ql/lib/semmle/code/powershell/ScriptBlockExpr.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ScriptBlockExpr.qll
@@ -1,9 +1,9 @@
-import powershell
+private import Raw
class ScriptBlockExpr extends @script_block_expression, Expr {
override SourceLocation getLocation() { script_block_expression_location(this, result) }
- override string toString() { result = "{...}" }
-
ScriptBlock getBody() { script_block_expression(this, result) }
+
+ final override Ast getChild(ChildIndex i) { i = ScriptBlockExprBody() and result = this.getBody() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/SourceLocation.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SourceLocation.qll
similarity index 97%
rename from powershell/ql/lib/semmle/code/powershell/SourceLocation.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SourceLocation.qll
index 8c70f06f7bc1..569de5e4229e 100644
--- a/powershell/ql/lib/semmle/code/powershell/SourceLocation.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SourceLocation.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
/**
* A location in source code, comprising of a source file and a segment of text
diff --git a/powershell/ql/lib/semmle/code/powershell/Statement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Statement.qll
similarity index 67%
rename from powershell/ql/lib/semmle/code/powershell/Statement.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Statement.qll
index 19bed527915a..881f86e94f26 100644
--- a/powershell/ql/lib/semmle/code/powershell/Statement.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Statement.qll
@@ -1,3 +1,3 @@
-import powershell
+private import Raw
class Stmt extends @statement, Ast { }
diff --git a/powershell/ql/lib/semmle/code/powershell/StatementBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StatementBlock.qll
similarity index 53%
rename from powershell/ql/lib/semmle/code/powershell/StatementBlock.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StatementBlock.qll
index c0dd9939079c..8fc5b4b238d6 100644
--- a/powershell/ql/lib/semmle/code/powershell/StatementBlock.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StatementBlock.qll
@@ -1,12 +1,4 @@
-import powershell
-private import semmle.code.powershell.internal.AstEscape::Private
-
-private module ReturnContainerInterpreter implements InterpretAstInputSig {
- class T = Ast;
-
- pragma[inline]
- T interpret(Ast a) { result = a }
-}
+private import Raw
class StmtBlock extends @statement_block, Ast {
override SourceLocation getLocation() { statement_block_location(this, result) }
@@ -23,10 +15,13 @@ class StmtBlock extends @statement_block, Ast {
TrapStmt getATrapStmt() { result = this.getTrapStmt(_) }
- override string toString() { result = "{...}" }
-
- /** Gets an element that may escape this `StmtBlock`. */
- Ast getAnElement() {
- result = this.(AstEscape::Element).getAnEscapingElement()
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = StmtBlockStmt(index) and
+ result = this.getStmt(index)
+ or
+ i = StmtBlockTrapStmt(index) and
+ result = this.getTrapStmt(index)
+ )
}
}
diff --git a/powershell/ql/lib/semmle/code/powershell/StringConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringConstantExpression.qll
similarity index 94%
rename from powershell/ql/lib/semmle/code/powershell/StringConstantExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringConstantExpression.qll
index d640817f99b3..dabbc2e2e73f 100644
--- a/powershell/ql/lib/semmle/code/powershell/StringConstantExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringConstantExpression.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
/** A string constant. */
class StringConstExpr extends @string_constant_expression, BaseConstExpr {
diff --git a/powershell/ql/lib/semmle/code/powershell/StringLiteral.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringLiteral.qll
similarity index 96%
rename from powershell/ql/lib/semmle/code/powershell/StringLiteral.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringLiteral.qll
index a7f85ece8e42..e24ed143cdf1 100644
--- a/powershell/ql/lib/semmle/code/powershell/StringLiteral.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/StringLiteral.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class StringLiteral extends @string_literal {
int getNumContinuations() { result = strictcount(int i | exists(this.getContinuation(i))) }
diff --git a/powershell/ql/lib/semmle/code/powershell/SubExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SubExpression.qll
similarity index 65%
rename from powershell/ql/lib/semmle/code/powershell/SubExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SubExpression.qll
index df39df46a48a..b2caafdc304d 100644
--- a/powershell/ql/lib/semmle/code/powershell/SubExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SubExpression.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
// TODO: Should we remove this from the dbscheme?
class ExpandableSubExpr extends @sub_expression, Expr {
@@ -6,5 +6,7 @@ class ExpandableSubExpr extends @sub_expression, Expr {
StmtBlock getExpr() { sub_expression(this, result) }
- final override string toString() { result = "$(...)" }
+ final override Ast getChild(ChildIndex i) {
+ i = ExpandableSubExprExpr() and result = this.getExpr()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/SwitchStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SwitchStmt.qll
similarity index 65%
rename from powershell/ql/lib/semmle/code/powershell/SwitchStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SwitchStmt.qll
index 8dca8f0b91c2..bb8a30b6bd34 100644
--- a/powershell/ql/lib/semmle/code/powershell/SwitchStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/SwitchStmt.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class SwitchStmt extends LabeledStmt, @switch_statement {
final override Location getLocation() { switch_statement_location(this, result) }
@@ -21,5 +21,19 @@ class SwitchStmt extends LabeledStmt, @switch_statement {
int getNumberOfCases() { result = count(this.getACase()) }
- final override string toString() { result = "switch(...) {...}" }
+ final override Ast getChild(ChildIndex i) {
+ i = SwitchStmtCond() and
+ result = this.getCondition()
+ or
+ i = SwitchStmtDefault() and
+ result = this.getDefault()
+ or
+ exists(int index |
+ i = SwitchStmtCase(index) and
+ result = this.getCase(index)
+ or
+ i = SwitchStmtPat(index) and
+ result = this.getPattern(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/TernaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TernaryExpression.qll
similarity index 67%
rename from powershell/ql/lib/semmle/code/powershell/TernaryExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TernaryExpression.qll
index 19af31478fcf..9b6e49e6ddb5 100644
--- a/powershell/ql/lib/semmle/code/powershell/TernaryExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TernaryExpression.qll
@@ -1,7 +1,6 @@
-import powershell
+private import Raw
class ConditionalExpr extends @ternary_expression, Expr {
- override string toString() { result = "...?...:..." }
override SourceLocation getLocation() { ternary_expression_location(this, result) }
@@ -20,4 +19,15 @@ class ConditionalExpr extends @ternary_expression, Expr {
}
Expr getABranch() { result = this.getBranch(_) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = CondExprCond() and
+ result = this.getCondition()
+ or
+ i = CondExprTrue() and
+ result = this.getIfTrue()
+ or
+ i = CondExprFalse() and
+ result = this.getIfFalse()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ThrowStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ThrowStmt.qll
similarity index 67%
rename from powershell/ql/lib/semmle/code/powershell/ThrowStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ThrowStmt.qll
index af8ccaab5f5b..58f357a8efeb 100644
--- a/powershell/ql/lib/semmle/code/powershell/ThrowStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/ThrowStmt.qll
@@ -1,13 +1,11 @@
-import powershell
+private import Raw
class ThrowStmt extends @throw_statement, Stmt {
override SourceLocation getLocation() { throw_statement_location(this, result) }
- override string toString() {
- if this.hasPipeline() then result = "throw ..." else result = "throw"
- }
-
PipelineBase getPipeline() { throw_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
+
+ final override Ast getChild(ChildIndex i) { i = ThrowStmtPipeline() and result = this.getPipeline() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/TokenKind.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TokenKind.qll
similarity index 100%
rename from powershell/ql/lib/semmle/code/powershell/TokenKind.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TokenKind.qll
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TrapStatement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TrapStatement.qll
new file mode 100644
index 000000000000..d03605161a08
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TrapStatement.qll
@@ -0,0 +1,17 @@
+private import Raw
+
+class TrapStmt extends @trap_statement, Stmt {
+ override SourceLocation getLocation() { trap_statement_location(this, result) }
+
+ StmtBlock getBody() { trap_statement(this, result) } // TODO: Fix type in dbscheme
+
+ TypeConstraint getTypeConstraint() { trap_statement_type(this, result) }
+
+ override Ast getChild(ChildIndex i) {
+ i = TrapStmtBody() and
+ result = this.getBody()
+ or
+ i = TrapStmtTypeConstraint() and
+ result = this.getTypeConstraint()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/TryStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TryStmt.qll
similarity index 61%
rename from powershell/ql/lib/semmle/code/powershell/TryStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TryStmt.qll
index 300c59712e6b..149aacbf040b 100644
--- a/powershell/ql/lib/semmle/code/powershell/TryStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TryStmt.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
class TryStmt extends @try_statement, Stmt {
override SourceLocation getLocation() { try_statement_location(this, result) }
- override string toString() { result = "try {...}" }
-
CatchClause getCatchClause(int i) { try_statement_catch_clause(this, i, result) }
CatchClause getACatchClause() { result = this.getCatchClause(_) }
@@ -15,4 +13,17 @@ class TryStmt extends @try_statement, Stmt {
StmtBlock getBody() { try_statement(this, result) }
predicate hasFinally() { exists(this.getFinally()) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = TryStmtBody() and
+ result = this.getBody()
+ or
+ exists(int index |
+ i = TryStmtCatchClause(index) and
+ result = this.getCatchClause(index)
+ )
+ or
+ i = TryStmtFinally() and
+ result = this.getFinally()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/Type.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Type.qll
similarity index 51%
rename from powershell/ql/lib/semmle/code/powershell/Type.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Type.qll
index d67aea74ad15..bd386eb461ff 100644
--- a/powershell/ql/lib/semmle/code/powershell/Type.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/Type.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
-class Type extends @type_definition, Stmt {
+class TypeStmt extends @type_definition, Stmt {
override SourceLocation getLocation() { type_definition_location(this, result) }
- override string toString() { result = this.getName() }
-
string getName() { type_definition(this, result, _, _, _, _) }
Member getMember(int i) { type_definition_members(this, i, result) }
@@ -12,20 +10,23 @@ class Type extends @type_definition, Stmt {
Member getAMember() { result = this.getMember(_) }
Method getMethod(string name) {
- result.getMember() = this.getAMember() and
- result.hasName(name)
- }
-
- Constructor getAConstructor() {
- result = this.getAMethod() and
- result.getName() = this.getName()
+ result = this.getAMember() and
+ result.getName() = name
}
- Method getAMethod() { result = this.getMethod(_) }
-
TypeConstraint getBaseType(int i) { type_definition_base_type(this, i, result) }
TypeConstraint getABaseType() { result = this.getBaseType(_) }
- Type getASubtype() { result.getABaseType().getName() = this.getName() }
+ TypeStmt getASubtype() { result.getABaseType().getName() = this.getName() }
+
+ final override Ast getChild(ChildIndex i) {
+ exists(int index |
+ i = TypeStmtMember(index) and
+ result = this.getMember(index)
+ or
+ i = TypeStmtBaseType(index) and
+ result = this.getBaseType(index)
+ )
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/TypeConstraint.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeConstraint.qll
similarity index 83%
rename from powershell/ql/lib/semmle/code/powershell/TypeConstraint.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeConstraint.qll
index 970afcb5b70c..c5552aaf1731 100644
--- a/powershell/ql/lib/semmle/code/powershell/TypeConstraint.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeConstraint.qll
@@ -1,4 +1,4 @@
-import powershell
+private import Raw
class TypeConstraint extends @type_constraint, AttributeBase {
override SourceLocation getLocation() { type_constraint_location(this, result) }
@@ -8,6 +8,4 @@ class TypeConstraint extends @type_constraint, AttributeBase {
/** Gets the full name of this type constraint including namespaces. */
string getFullName() { type_constraint(this, _, result) }
-
- override string toString() { result = this.getName() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/TypeExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeExpression.qll
similarity index 55%
rename from powershell/ql/lib/semmle/code/powershell/TypeExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeExpression.qll
index 9817a5ca07a7..50fbc41bbac3 100644
--- a/powershell/ql/lib/semmle/code/powershell/TypeExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/TypeExpression.qll
@@ -1,14 +1,10 @@
-import powershell
+private import Raw
class TypeNameExpr extends @type_expression, Expr {
string getName() { type_expression(this, result, _) }
- string getFullyQualifiedName() { type_expression(this, _, result) }
-
- override string toString() { result = this.getName() }
-
override SourceLocation getLocation() { type_expression_location(this, result) }
/** Gets the type referred to by this `TypeNameExpr`. */
- Type getType() { result.getName() = this.getName() }
+ TypeStmt getType() { result.getName() = this.getName() }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UnaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UnaryExpression.qll
new file mode 100644
index 000000000000..74370a61b19e
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UnaryExpression.qll
@@ -0,0 +1,11 @@
+private import Raw
+
+class UnaryExpr extends @unary_expression, Expr {
+ override SourceLocation getLocation() { unary_expression_location(this, result) }
+
+ int getKind() { unary_expression(this, _, result, _) }
+
+ Expr getOperand() { unary_expression(this, result, _, _) }
+
+ final override Ast getChild(ChildIndex i) { i = UnaryExprOp() and result = this.getOperand() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingExpression.qll
new file mode 100644
index 000000000000..527b17c0668a
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingExpression.qll
@@ -0,0 +1,12 @@
+private import Raw
+
+class UsingExpr extends @using_expression, Expr {
+ override SourceLocation getLocation() { using_expression_location(this, result) }
+
+ Expr getExpr() { using_expression(this, result) }
+
+ override Ast getChild(ChildIndex i) {
+ i = UsingExprExpr() and
+ result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/UsingStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingStmt.qll
similarity index 87%
rename from powershell/ql/lib/semmle/code/powershell/UsingStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingStmt.qll
index 2278409c0a55..46614401daa9 100644
--- a/powershell/ql/lib/semmle/code/powershell/UsingStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/UsingStmt.qll
@@ -1,10 +1,8 @@
-import powershell
+private import Raw
class UsingStmt extends @using_statement, Stmt {
override SourceLocation getLocation() { using_statement_location(this, result) }
- override string toString() { result = "using ..." }
-
string getName() {
exists(StringConstExpr const |
using_statement_name(this, const) and // TODO: Change dbscheme
diff --git a/powershell/ql/lib/semmle/code/powershell/VariableExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/VariableExpression.qll
similarity index 51%
rename from powershell/ql/lib/semmle/code/powershell/VariableExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/VariableExpression.qll
index b07774a29246..00bc726699c5 100644
--- a/powershell/ql/lib/semmle/code/powershell/VariableExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/VariableExpression.qll
@@ -1,13 +1,6 @@
-import powershell
-private import internal.ExplicitWrite::Private
-
-private predicate isParameterName(@variable_expression ve) { parameter(_, ve, _, _) }
+private import Raw
class VarAccess extends @variable_expression, Expr {
- VarAccess() { not isParameterName(this) }
-
- override string toString() { result = this.getUserPath() }
-
override SourceLocation getLocation() { variable_expression_location(this, result) }
string getUserPath() { variable_expression(this, result, _, _, _, _, _, _, _, _, _, _) }
@@ -31,29 +24,25 @@ class VarAccess extends @variable_expression, Expr {
boolean isVariable() { variable_expression(this, _, _, _, _, _, _, _, _, _, result, _) }
boolean isDriveQualified() { variable_expression(this, _, _, _, _, _, _, _, _, _, _, result) }
-
- Variable getVariable() { result.getAnAccess() = this }
}
-private predicate isImplicitVariableWriteAccess(Expr e) { none() }
-
-class VarReadAccess extends VarAccess {
- VarReadAccess() { not this instanceof VarWriteAccess }
+class ThisAccess extends VarAccess {
+ ThisAccess() { this.getUserPath() = "this" }
}
-class VarWriteAccess extends VarAccess {
- VarWriteAccess() { isExplicitWrite(this, _) or isImplicitVariableWriteAccess(this) }
-
- predicate isExplicit(AssignStmt assign) { isExplicitWrite(this, assign) }
-
- predicate isImplicit() { isImplicitVariableWriteAccess(this) }
+predicate isEnvVariableAccess(VarAccess va, string env) {
+ va.getUserPath().toLowerCase() = "env:" + env
}
-/** An access to an environment variable such as `$Env:PATH` */
-class EnvVarAccess extends VarAccess {
- EnvVarAccess() { super.getVariable() instanceof EnvVariable }
-
- override EnvVariable getVariable() { result = super.getVariable() }
-
- string getEnvironmentVariable() { result = this.getVariable().getEnvironmentVariable() }
+predicate isAutomaticVariableAccess(VarAccess va, string var) {
+ va.getUserPath().toLowerCase() =
+ [
+ "args", "consolefilename", "enabledexperimentalfeatures", "error", "event", "eventargs",
+ "eventsubscriber", "executioncontext", "home", "host", "input", "iscoreclr", "islinux",
+ "ismacos", "iswindows", "lastexitcode", "myinvocation", "nestedpromptlevel", "pid", "profile",
+ "psboundparameters", "pscmdlet", "pscommandpath", "psculture", "psdebugcontext", "psedition",
+ "pshome", "psitem", "psscriptroot", "pssenderinfo", "psuiculture", "psversiontable", "pwd",
+ "sender", "shellid", "stacktrace"
+ ] and
+ var = va.getUserPath().toLowerCase()
}
diff --git a/powershell/ql/lib/semmle/code/powershell/WhileStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/WhileStmt.qll
similarity index 60%
rename from powershell/ql/lib/semmle/code/powershell/WhileStmt.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/WhileStmt.qll
index 9f244d3ed78a..92ced49b4230 100644
--- a/powershell/ql/lib/semmle/code/powershell/WhileStmt.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Raw/WhileStmt.qll
@@ -1,11 +1,15 @@
-import powershell
+private import Raw
class WhileStmt extends @while_statement, LoopStmt {
override SourceLocation getLocation() { while_statement_location(this, result) }
- override string toString() { result = "while(...) {...}" }
-
PipelineBase getCondition() { while_statement_condition(this, result) }
final override StmtBlock getBody() { while_statement(this, result) }
+
+ final override Ast getChild(ChildIndex i) {
+ i = WhileStmtCond() and result = this.getCondition()
+ or
+ i = WhileStmtBody() and result = this.getBody()
+ }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Redirection.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Redirection.qll
new file mode 100644
index 000000000000..050c59286e13
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Redirection.qll
@@ -0,0 +1,18 @@
+private import AstImport
+
+class Redirection extends Ast, TRedirection {
+ Expr getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, redirectionExpr(), result)
+ or
+ not synthChild(r, redirectionExpr(), _) and
+ result = getResultAst(r.(Raw::Redirection).getExpr())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = redirectionExpr() and result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ReturnStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ReturnStmt.qll
new file mode 100644
index 000000000000..d54937316547
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ReturnStmt.qll
@@ -0,0 +1,25 @@
+private import AstImport
+
+class ReturnStmt extends Stmt, TReturnStmt {
+ override string toString() {
+ if this.hasPipeline() then result = "return ..." else result = "return"
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = returnStmtPipeline() and
+ result = this.getPipeline()
+ }
+
+ predicate hasPipeline() { exists(this.getPipeline()) }
+
+ Expr getPipeline() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, returnStmtPipeline(), result)
+ or
+ not synthChild(r, returnStmtPipeline(), _) and
+ result = getResultAst(r.(Raw::ReturnStmt).getPipeline())
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Scopes.qll
similarity index 53%
rename from powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/Scopes.qll
index 49d182548fdd..52212cf5ea22 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Scopes.qll
@@ -1,5 +1,4 @@
-private import powershell
-private import ControlFlowGraphImpl
+private import AstImport
/** Gets the enclosing scope of `n`. */
Scope scopeOf(Ast n) {
@@ -10,11 +9,15 @@ Scope scopeOf(Ast n) {
)
}
-/**
- * A variable scope. This is either a top-level (file), a module, a class,
- * or a callable.
- */
-class Scope extends Ast, ScriptBlock {
+class Scope extends Ast {
+ Scope() { getRawAst(this) instanceof Raw::Scope }
+
/** Gets the outer scope, if any. */
Scope getOuterScope() { result = scopeOf(this) }
+
+ UsingStmt getAnActiveUsingStmt() { result.getAnAffectedScope() = this }
+}
+
+module Scope {
+ class Range extends Raw::Scope { }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlock.qll
new file mode 100644
index 000000000000..ad71dd424263
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlock.qll
@@ -0,0 +1,122 @@
+private import AstImport
+
+class ScriptBlock extends Ast, TScriptBlock {
+ override string toString() {
+ if this.isTopLevel()
+ then result = this.getLocation().getFile().getBaseName()
+ else result = "{...}"
+ }
+
+ NamedBlock getProcessBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, scriptBlockProcessBlock(), result)
+ or
+ not synthChild(r, scriptBlockProcessBlock(), _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getProcessBlock())
+ )
+ }
+
+ NamedBlock getBeginBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, scriptBlockBeginBlock(), result)
+ or
+ not synthChild(r, scriptBlockBeginBlock(), _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getBeginBlock())
+ )
+ }
+
+ UsingStmt getUsingStmt(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = scriptBlockUsing(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getUsing(i))
+ )
+ }
+
+ UsingStmt getAUsingStmt() { result = this.getUsingStmt(_) }
+
+ NamedBlock getEndBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, scriptBlockEndBlock(), result)
+ or
+ not synthChild(r, scriptBlockEndBlock(), _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getEndBlock())
+ )
+ }
+
+ NamedBlock getDynamicBlock() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, scriptBlockDynParamBlock(), result)
+ or
+ not synthChild(r, scriptBlockDynParamBlock(), _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getDynamicParamBlock())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = scriptBlockBeginBlock() and
+ result = this.getBeginBlock()
+ or
+ i = scriptBlockProcessBlock() and
+ result = this.getProcessBlock()
+ or
+ i = scriptBlockEndBlock() and
+ result = this.getEndBlock()
+ or
+ i = scriptBlockDynParamBlock() and
+ result = this.getDynamicBlock()
+ or
+ exists(int index |
+ i = scriptBlockAttr(index) and
+ result = this.getAttribute(index)
+ )
+ or
+ exists(int index |
+ i = funParam(index) and
+ result = this.getParameter(index)
+ )
+ or
+ exists(int index |
+ i = scriptBlockUsing(index) and
+ result = this.getUsingStmt(index)
+ )
+ }
+
+ Parameter getParameter(int i) {
+ synthChild(getRawAst(this), funParam(i), result)
+ or
+ any(Synthesis s).pipelineParameterHasIndex(this, i) and
+ synthChild(getRawAst(this), PipelineParamVar(), result)
+ or
+ i = -1 and
+ synthChild(getRawAst(this), ThisVar(), result)
+ }
+
+ /**
+ * Gets a parameter of this block.
+ */
+ Parameter getAParameter() { result = this.getParameter(_) }
+
+ int getNumberOfParameters() { result = count(this.getAParameter()) }
+
+ predicate isTopLevel() { not exists(this.getParent()) }
+
+ Attribute getAttribute(int i) {
+ // We attach the attributes to the function since we got rid of parameter blocks
+ exists(ChildIndex index, Raw::Ast r | index = scriptBlockAttr(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::ScriptBlock).getParamBlock().getAttribute(i))
+ )
+ }
+
+ Attribute getAnAttribute() { result = this.getAttribute(_) }
+}
+
+class TopLevelScriptBlock extends ScriptBlock {
+ TopLevelScriptBlock() { this.isTopLevel() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlockExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlockExpr.qll
new file mode 100644
index 000000000000..1bfc559e66a7
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ScriptBlockExpr.qll
@@ -0,0 +1,20 @@
+private import AstImport
+
+class ScriptBlockExpr extends Expr, TScriptBlockExpr {
+ override string toString() { result = "{...}" }
+
+ ScriptBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, scriptBlockExprBody(), result)
+ or
+ not synthChild(r, scriptBlockExprBody(), _) and
+ result = getResultAst(r.(Raw::ScriptBlockExpr).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = scriptBlockExprBody() and result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/SourceLocation.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/SourceLocation.qll
new file mode 100644
index 000000000000..270befbece57
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/SourceLocation.qll
@@ -0,0 +1 @@
+import Raw.SourceLocation
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Statement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Statement.qll
new file mode 100644
index 000000000000..802413b3865e
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Statement.qll
@@ -0,0 +1,3 @@
+private import AstImport
+
+class Stmt extends Ast, TStmt { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/StatementBlock.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/StatementBlock.qll
new file mode 100644
index 000000000000..58a0fb1a19aa
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/StatementBlock.qll
@@ -0,0 +1,42 @@
+private import AstImport
+
+class StmtBlock extends Stmt, TStmtBlock {
+ pragma[nomagic]
+ Stmt getStmt(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = stmtBlockStmt(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::StmtBlock).getStmt(i))
+ )
+ }
+
+ Stmt getAStmt() { result = this.getStmt(_) }
+
+ TrapStmt getTrapStmt(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = stmtBlockTrapStmt(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::StmtBlock).getTrapStmt(i))
+ )
+ }
+
+ TrapStmt getATrapStmt() { result = this.getTrapStmt(_) }
+
+ int getNumberOfStmts() { result = count(this.getAStmt()) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = stmtBlockStmt(index) and
+ result = this.getStmt(index)
+ or
+ i = stmtBlockTrapStmt(index) and
+ result = this.getTrapStmt(index)
+ )
+ }
+
+ override string toString() { result = "{...}" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Stmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Stmt.qll
new file mode 100644
index 000000000000..802413b3865e
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Stmt.qll
@@ -0,0 +1,3 @@
+private import AstImport
+
+class Stmt extends Ast, TStmt { }
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/StringConstantExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/StringConstantExpression.qll
new file mode 100644
index 000000000000..95261d31052f
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/StringConstantExpression.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class StringConstExpr extends Expr, TStringConstExpr {
+ string getValueString() { result = getRawAst(this).(Raw::StringConstExpr).getValue().getValue() }
+
+ override string toString() { result = this.getValueString() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/SubExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/SubExpression.qll
new file mode 100644
index 000000000000..2208828595a8
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/SubExpression.qll
@@ -0,0 +1,20 @@
+private import AstImport
+
+class ExpandableSubExpr extends Expr, TExpandableSubExpr {
+ StmtBlock getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, expandableSubExprExpr(), result)
+ or
+ not synthChild(r, expandableSubExprExpr(), _) and
+ result = getResultAst(r.(Raw::ExpandableSubExpr).getExpr())
+ )
+ }
+
+ final override string toString() { result = "$(...)" }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = expandableSubExprExpr() and result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/SwitchStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/SwitchStmt.qll
new file mode 100644
index 000000000000..ed3ec27ef2fe
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/SwitchStmt.qll
@@ -0,0 +1,65 @@
+private import AstImport
+
+class SwitchStmt extends Stmt, TSwitchStmt {
+ final override string toString() { result = "switch(...) {...}" }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, switchStmtCond(), result)
+ or
+ not synthChild(r, switchStmtCond(), _) and
+ result = getResultAst(r.(Raw::SwitchStmt).getCondition())
+ )
+ }
+
+ StmtBlock getDefault() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, switchStmtDefault(), result)
+ or
+ not synthChild(r, switchStmtDefault(), _) and
+ result = getResultAst(r.(Raw::SwitchStmt).getDefault())
+ )
+ }
+
+ StmtBlock getCase(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = switchStmtCase(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::SwitchStmt).getCase(i))
+ )
+ }
+
+ StmtBlock getACase() { result = this.getCase(_) }
+
+ int getNumberOfCases() { result = getRawAst(this).(Raw::SwitchStmt).getNumberOfCases() }
+
+ Expr getPattern(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = switchStmtPat(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::SwitchStmt).getPattern(i))
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = switchStmtCond() and
+ result = this.getCondition()
+ or
+ i = switchStmtDefault() and
+ result = this.getDefault()
+ or
+ exists(int index |
+ i = switchStmtCase(index) and
+ result = this.getCase(index)
+ or
+ i = switchStmtPat(index) and
+ result = this.getPattern(index)
+ )
+ }
+
+ Expr getAPattern() { result = this.getPattern(_) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Synthesis.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Synthesis.qll
new file mode 100644
index 000000000000..8aa76fd11a49
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Synthesis.qll
@@ -0,0 +1,772 @@
+private import TAst
+private import Ast
+private import Location
+private import Variable
+private import TypeConstraint
+private import Expr
+private import Parameter
+private import ExprStmt
+private import NamedBlock
+private import FunctionBase
+private import ScriptBlock
+private import Command
+private import Internal::Private
+private import Type
+private import Scopes
+private import BoolLiteral
+private import Member
+private import EnvVariable
+private import Raw.Raw as Raw
+private import codeql.util.Boolean
+private import AutomaticVariable
+
+newtype VarKind =
+ ThisVarKind() or
+ ParamVarRealKind() or
+ ParamVarPipelineKind() or
+ PipelineIteratorKind() or
+ PipelineByPropertyNameIteratorKind(string name) {
+ exists(Raw::ProcessBlock pb |
+ name = pb.getScriptBlock().getParamBlock().getAPipelineByPropertyNameParameter().getName()
+ )
+ }
+
+newtype SynthKind =
+ ExprStmtKind() or
+ VarAccessRealKind(VariableReal v) or
+ VarAccessSynthKind(VariableSynth v) or
+ FunctionSynthKind() or
+ TypeSynthKind() or
+ BoolLiteralKind(Boolean b) or
+ NullLiteralKind() or
+ EnvVariableKind(string var) { Raw::isEnvVariableAccess(_, var) } or
+ AutomaticVariableKind(string var) { Raw::isAutomaticVariableAccess(_, var) } or
+ VarSynthKind(VarKind k)
+
+newtype Child =
+ SynthChild(SynthKind kind) or
+ RealChildRef(TAstReal n) or
+ SynthChildRef(TAstSynth n)
+
+pragma[inline]
+private Child childRef(TAst n) {
+ result = RealChildRef(n)
+ or
+ result = SynthChildRef(n)
+}
+
+private newtype TSynthesis = MkSynthesis()
+
+class Synthesis extends TSynthesis {
+ predicate child(Raw::Ast parent, ChildIndex i, Child child) { none() }
+
+ Location getLocation(Ast n) { none() }
+
+ predicate isRelevant(Raw::Ast a) { none() }
+
+ string toString(Ast n) { none() }
+
+ Ast getResultAstImpl(Raw::Ast r) { none() }
+
+ predicate explicitAssignment(Raw::Ast dest, string name, Raw::Ast assignment) { none() }
+
+ predicate implicitAssignment(Raw::Ast dest, string name) { none() }
+
+ predicate variableSynthName(VariableSynth v, string name) { none() }
+
+ predicate exprStmtExpr(ExprStmt e, Expr expr) { none() }
+
+ predicate parameterStaticType(Parameter p, string type) { none() }
+
+ predicate isPipelineParameter(Parameter p) { none() }
+
+ predicate pipelineParameterHasIndex(ScriptBlock s, int i) { none() }
+
+ predicate functionName(FunctionBase f, string name) { none() }
+
+ predicate memberName(Member m, string name) { none() }
+
+ predicate typeName(Type t, string name) { none() }
+
+ predicate typeMember(Type t, int i, Member m) { none() }
+
+ predicate functionScriptBlock(FunctionBase f, ScriptBlock block) { none() }
+
+ predicate isNamedArgument(CmdCall call, int i, string name) { none() }
+
+ predicate booleanValue(BoolLiteral b, boolean value) { none() }
+
+ predicate envVariableName(EnvVariable var, string name) { none() }
+
+ predicate automaticVariableName(AutomaticVariable var, string name) { none() }
+
+ final string toString() { none() }
+}
+
+/** Gets the user-facing AST element that is generated from `r`. */
+Ast getResultAst(Raw::Ast r) {
+ not any(Synthesis s).isRelevant(r) and
+ toRaw(result) = r
+ or
+ any(Synthesis s).isRelevant(r) and
+ result = any(Synthesis s).getResultAstImpl(r)
+}
+
+Raw::Ast getRawAst(Ast r) { r = getResultAst(result) }
+
+private module ThisSynthesis {
+ private class ThisSynthesis extends Synthesis {
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ parent instanceof Raw::MethodScriptBlock and
+ i = ThisVar() and
+ child = SynthChild(VarSynthKind(ThisVarKind()))
+ or
+ parent.getChild(toRawChildIndex(i)).(Raw::VarAccess).getUserPath().toLowerCase() = "this" and
+ child = SynthChild(VarAccessSynthKind(TVariableSynth(parent.getScope(), ThisVar())))
+ }
+
+ override predicate variableSynthName(VariableSynth v, string name) {
+ v = TVariableSynth(_, ThisVar()) and
+ name = "this"
+ }
+
+ override Location getLocation(Ast n) {
+ exists(Raw::Ast scope |
+ n = TVariableSynth(scope, ThisVar()) and
+ result = scope.getLocation()
+ )
+ }
+ }
+}
+
+private module SetVariableAssignment {
+ private class SetVariableAssignment extends Synthesis {
+ override predicate explicitAssignment(Raw::Ast dest, string name, Raw::Ast assignment) {
+ exists(Raw::Cmd cmd |
+ assignment = cmd and
+ cmd.getCommandName().toLowerCase() = "set-variable" and
+ cmd.getNamedArgument("name") = dest and
+ name = dest.(Raw::StringConstExpr).getValue().getValue()
+ )
+ }
+ }
+}
+
+/**
+ * Syntesize parameters from parameter blocks and function definitions
+ * so that they have a uniform API.
+ */
+private module ParameterSynth {
+ private class ParameterSynth extends Synthesis {
+ final override predicate isRelevant(Raw::Ast a) { a = any(Scope::Range r).getAParameter() }
+
+ private predicate parameter(
+ Raw::Ast parent, ChildIndex i, Raw::Parameter p, Child child, boolean isPipelineParameter
+ ) {
+ exists(Scope::Range r, int index |
+ p = r.getParameter(index) and
+ parent = r and
+ i = funParam(index) and
+ child = SynthChild(VarSynthKind(ParamVarRealKind())) and
+ if p instanceof Raw::PipelineParameter
+ then isPipelineParameter = true
+ else isPipelineParameter = false
+ )
+ }
+
+ final override predicate isPipelineParameter(Parameter p) {
+ exists(Raw::Ast parent, ChildIndex i |
+ parent = getRawAst(p.getFunction().getBody()) and
+ this.isPipelineParameterChild(parent, _, i) and
+ p = TVariableSynth(parent, i)
+ )
+ }
+
+ override predicate implicitAssignment(Raw::Ast dest, string name) {
+ exists(Raw::Parameter p |
+ dest = p and
+ name = p.getName()
+ )
+ }
+
+ final override predicate variableSynthName(VariableSynth v, string name) {
+ exists(Raw::Ast parent, int i, Raw::Parameter p |
+ this.parameter(parent, FunParam(i), p, _, false) and
+ v = TVariableSynth(parent, FunParam(i)) and
+ name = p.getName()
+ )
+ or
+ exists(Raw::Ast parent |
+ this.child(parent, PipelineParamVar(), _) and
+ v = TVariableSynth(parent, PipelineParamVar()) and
+ name = "[synth] pipeline"
+ )
+ }
+
+ private predicate isPipelineParameterChild(Raw::Ast parent, int index, ChildIndex i) {
+ exists(Scope::Range r | parent = r and i = PipelineParamVar() |
+ r.getParameter(index) instanceof Raw::PipelineParameter
+ or
+ not r.getAParameter() instanceof Raw::PipelineParameter and
+ index = synthPipelineParameterChildIndex(r)
+ )
+ }
+
+ final override predicate pipelineParameterHasIndex(ScriptBlock s, int i) {
+ exists(Raw::ScriptBlock scriptBlock |
+ s = TScriptBlock(scriptBlock) and
+ this.isPipelineParameterChild(scriptBlock, i, _)
+ )
+ }
+
+ final override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ // Synthesize parameters
+ this.parameter(parent, i, _, child, false)
+ or
+ // Synthesize pipeline parameter
+ child = SynthChild(VarSynthKind(ParamVarPipelineKind())) and
+ this.isPipelineParameterChild(parent, _, i)
+ or
+ // Synthesize default values
+ exists(Raw::Parameter q |
+ parent = q and
+ this.parameter(_, _, q, _, _)
+ |
+ i = paramDefaultVal() and
+ child = childRef(getResultAst(q.getDefaultValue()))
+ or
+ exists(int index |
+ i = paramAttr(index) and
+ child = childRef(getResultAst(q.getAttribute(index)))
+ )
+ )
+ }
+
+ final override Parameter getResultAstImpl(Raw::Ast r) {
+ exists(Raw::Ast parent, int i |
+ this.parameter(parent, FunParam(i), r, _, false) and
+ result = TVariableSynth(parent, FunParam(i))
+ )
+ or
+ exists(Scope::Range scope, int i, ChildIndex index |
+ scope.getParameter(i) = r and
+ this.isPipelineParameterChild(scope, i, index) and
+ result = TVariableSynth(scope, index)
+ )
+ }
+
+ final override Location getLocation(Ast n) {
+ exists(Raw::Ast parent, Raw::Parameter p, int i |
+ this.parameter(parent, _, p, _, _) and
+ n = TVariableSynth(parent, FunParam(i)) and
+ result = p.getLocation()
+ )
+ }
+
+ final override predicate parameterStaticType(Parameter n, string type) {
+ exists(Raw::Ast parent, int i, Raw::Parameter p |
+ this.parameter(parent, FunParam(i), p, _, false) and
+ n = TVariableSynth(parent, FunParam(i)) and
+ type = p.getStaticType()
+ )
+ }
+ }
+}
+
+/**
+ * Holds if `child` is a child of `n` that is a `Stmt` in the raw AST, but should
+ * be mapped to an `Expr` in the synthesized AST.
+ */
+private predicate mustHaveExprChild(Raw::Ast n, Raw::Stmt child) {
+ n.(Raw::AssignStmt).getRightHandSide() = child
+ or
+ n.(Raw::Pipeline).getAComponent() = child
+ or
+ n.(Raw::ReturnStmt).getPipeline() = child
+ or
+ n.(Raw::HashTableExpr).getAStmt() = child
+ or
+ n.(Raw::ParenExpr).getBase() = child
+ or
+ n.(Raw::DoUntilStmt).getCondition() = child
+ or
+ n.(Raw::DoWhileStmt).getCondition() = child
+ or
+ n.(Raw::ExitStmt).getPipeline() = child
+ or
+ n.(Raw::ForEachStmt).getIterableExpr() = child
+ or
+ // TODO: What to do about initializer and iterator?
+ exists(Raw::ForStmt for | n = for | for.getCondition() = child)
+ or
+ n.(Raw::IfStmt).getACondition() = child
+ or
+ n.(Raw::SwitchStmt).getCondition() = child
+ or
+ n.(Raw::ThrowStmt).getPipeline() = child
+ or
+ n.(Raw::WhileStmt).getCondition() = child
+}
+
+private class RawStmtThatShouldBeExpr extends Raw::Stmt {
+ RawStmtThatShouldBeExpr() {
+ this instanceof Raw::Cmd or
+ this instanceof Raw::Pipeline or
+ this instanceof Raw::PipelineChain or
+ this instanceof Raw::IfStmt
+ }
+
+ Expr getExpr() {
+ result = TCmd(this)
+ or
+ result = TPipeline(this)
+ or
+ result = TPipelineChain(this)
+ or
+ result = TIf(this)
+ }
+}
+
+/**
+ * Insert expr-to-stmt conversions where needed.
+ */
+private module ExprToStmtSynth {
+ private class ExprToStmtSynth extends Synthesis {
+ private predicate exprToSynthStmtChild(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt, Expr e) {
+ this.child(parent, i, SynthChild(ExprStmtKind()), stmt) and
+ e = stmt.(RawStmtThatShouldBeExpr).getExpr()
+ }
+
+ private predicate child(Raw::Ast parent, ChildIndex i, Child child, Raw::Stmt stmt) {
+ // Synthesize the expr-to-stmt conversion
+ child = SynthChild(ExprStmtKind()) and
+ stmt instanceof RawStmtThatShouldBeExpr and
+ parent.getChild(toRawChildIndex(i)) = stmt and
+ not mustHaveExprChild(parent, stmt)
+ }
+
+ final override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ this.child(parent, i, child, _)
+ }
+
+ final override predicate exprStmtExpr(ExprStmt e, Expr expr) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
+ e = TExprStmtSynth(parent, i) and
+ this.exprToSynthStmtChild(parent, i, stmt, expr)
+ )
+ }
+
+ final override Location getLocation(Ast n) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
+ n = TExprStmtSynth(parent, i) and
+ this.exprToSynthStmtChild(parent, i, stmt, _) and
+ result = stmt.getLocation()
+ )
+ }
+
+ final override string toString(Ast n) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
+ n = TExprStmtSynth(parent, i) and
+ this.exprToSynthStmtChild(parent, i, stmt, _) and
+ result = stmt.toString()
+ )
+ }
+ }
+}
+
+predicate excludeFunctionDefinitionStmt(Raw::FunctionDefinitionStmt f) {
+ // We don't care about function definition statements which define methods
+ // because they live inside a type anyway (and we don't have control-flow
+ // inside a type).
+ parent(f, any(Raw::Method m))
+}
+
+/**
+ * Synthesize function "declarations" from function definitions statements.
+ */
+private module FunctionSynth {
+ private class FunctionSynth extends Synthesis {
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ i = funDefFun() and
+ child = SynthChild(FunctionSynthKind()) and
+ exists(Raw::FunctionDefinitionStmt fundefStmt |
+ if excludeFunctionDefinitionStmt(fundefStmt)
+ then parent(fundefStmt, parent)
+ else parent = fundefStmt
+ )
+ }
+
+ override predicate functionName(FunctionBase f, string name) {
+ exists(Raw::FunctionDefinitionStmt fundefStmt |
+ f = TFunctionSynth(fundefStmt, _) and
+ fundefStmt.getName() = name
+ )
+ or
+ exists(Raw::TopLevelScriptBlock topLevelScriptBlock |
+ f = TTopLevelFunction(topLevelScriptBlock) and
+ name = "toplevel function for " + topLevelScriptBlock.getLocation().getFile().getBaseName()
+ )
+ }
+
+ override predicate functionScriptBlock(FunctionBase f, ScriptBlock block) {
+ exists(Raw::FunctionDefinitionStmt fundefStmt |
+ f = TFunctionSynth(fundefStmt, _) and
+ getResultAst(fundefStmt.getBody()) = block
+ )
+ or
+ exists(Raw::TopLevelScriptBlock topLevelScriptBlock |
+ block = getResultAst(topLevelScriptBlock) and
+ f = TTopLevelFunction(topLevelScriptBlock)
+ )
+ }
+
+ override Location getLocation(Ast n) {
+ exists(Raw::FunctionDefinitionStmt fundefStmt |
+ n = TFunctionSynth(fundefStmt, _) and
+ result = fundefStmt.getLocation()
+ )
+ }
+ }
+}
+
+private module TypeSynth {
+ private class TypeSynth extends Synthesis {
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ parent instanceof Raw::TypeStmt and
+ i = typeDefType() and
+ child = SynthChild(TypeSynthKind())
+ }
+
+ final override predicate typeMember(Type t, int i, Member m) {
+ exists(Raw::TypeStmt typeStmt |
+ t = TTypeSynth(typeStmt, _) and
+ m = getResultAst(typeStmt.getMember(i))
+ )
+ }
+
+ override predicate typeName(Type t, string name) {
+ exists(Raw::TypeStmt typeStmt |
+ t = TTypeSynth(typeStmt, _) and
+ typeStmt.getName() = name
+ )
+ }
+
+ override Location getLocation(Ast n) {
+ exists(Raw::TypeStmt typeStmt |
+ n = TTypeSynth(typeStmt, _) and
+ result = typeStmt.getLocation()
+ )
+ }
+ }
+}
+
+/**
+ * Remove the implicit expr-to-pipeline conversion.
+ */
+private module CmdExprRemoval {
+ private class CmdExprRemoval extends Synthesis {
+ final override predicate isRelevant(Raw::Ast a) { a instanceof Raw::CmdExpr }
+
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ // Remove the CmdExpr. There are two cases:
+ // - If the expression under the cmd expr exists in a place an expr is expected, then we're done
+ // - Otherwise, we need to synthesize an expr-to-stmt conversion with the expression as a child
+ exists(Raw::CmdExpr e, boolean exprCtx | this.parentHasCmdExpr(parent, i, e, exprCtx) |
+ if exprCtx = true
+ then child = childRef(getResultAst(e.getExpr()))
+ else child = SynthChild(ExprStmtKind())
+ )
+ or
+ // Synthesize the redirections from the redirections on the CmdExpr
+ exists(int index, Raw::CmdExpr e |
+ parent = e.getExpr() and
+ i = exprRedirection(index) and
+ child = childRef(getResultAst(e.getRedirection(index)))
+ )
+ }
+
+ final override predicate exprStmtExpr(ExprStmt e, Expr expr) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::CmdExpr cmd, Raw::Expr e0 |
+ e = TExprStmtSynth(parent, i) and
+ this.parentHasCmdExpr(parent, i, cmd, _) and
+ e0 = cmd.getExpr() and
+ expr = getResultAst(e0)
+ )
+ }
+
+ final override Ast getResultAstImpl(Raw::Ast r) {
+ exists(
+ Raw::CmdExpr cmdExpr, Raw::Expr e, Raw::ChildIndex rawIndex, Raw::Ast cmdParent,
+ ChildIndex i
+ |
+ r = cmdExpr and
+ cmdExpr.getExpr() = e and
+ cmdParent.getChild(rawIndex) = cmdExpr and
+ not mustHaveExprChild(cmdParent, cmdExpr) and
+ rawIndex = toRawChildIndex(i) and
+ result = TExprStmtSynth(cmdParent, i)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate parentHasCmdExpr(
+ Raw::Ast parent, ChildIndex i, Raw::CmdExpr cmdExpr, boolean exprCtx
+ ) {
+ exists(Raw::ChildIndex rawIndex |
+ rawIndex = toRawChildIndex(i) and
+ parent.getChild(rawIndex) = cmdExpr and
+ if mustHaveExprChild(parent, cmdExpr) then exprCtx = true else exprCtx = false
+ )
+ }
+
+ final override Location getLocation(Ast n) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::CmdExpr cmdStmt |
+ n = TExprStmtSynth(parent, i) and
+ this.parentHasCmdExpr(parent, i, cmdStmt, false) and
+ result = cmdStmt.getLocation()
+ )
+ }
+ }
+}
+
+/**
+ * Clean up arguments to commands by:
+ * - Removing the parameter name as an argument.
+ */
+private module CmdArguments {
+ private class CmdParameterRemoval extends Synthesis {
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ exists(Raw::Expr e |
+ this.rawChild(parent, i, e) and
+ child = childRef(getResultAst(e))
+ )
+ }
+
+ private predicate rawChild(Raw::Cmd cmd, ChildIndex i, Raw::Expr child) {
+ exists(int index |
+ i = cmdArgument(index) and
+ child = cmd.getArgument(index)
+ )
+ }
+
+ override predicate isNamedArgument(CmdCall call, int i, string name) {
+ exists(Raw::Cmd cmd, Raw::Expr e, Raw::CmdParameter p |
+ this.rawChild(cmd, cmdArgument(i), e) and
+ call = getResultAst(cmd) and
+ p.getName().toLowerCase() = name
+ |
+ p.getExpr() = e
+ or
+ exists(ChildIndex j, int jndex |
+ j = cmdElement_(jndex) and
+ not exists(p.getExpr()) and
+ cmd.getChild(toRawChildIndex(j)) = p and
+ cmd.getChild(toRawChildIndex(cmdElement_(jndex + 1))) = e
+ )
+ )
+ }
+ }
+}
+
+/**
+ * Synthesize literals from known constant strings.
+ */
+private module LiteralSynth {
+ private class LiteralSynth extends Synthesis {
+ final override predicate isRelevant(Raw::Ast a) {
+ exists(Raw::VarAccess va | a = va |
+ va.getUserPath().toLowerCase() = "true"
+ or
+ va.getUserPath().toLowerCase() = "false"
+ or
+ va.getUserPath().toLowerCase() = "null"
+ or
+ Raw::isEnvVariableAccess(va, _)
+ or
+ Raw::isAutomaticVariableAccess(va, _)
+ )
+ }
+
+ final override Expr getResultAstImpl(Raw::Ast r) {
+ exists(Raw::Ast parent, ChildIndex i | this.child(parent, i, _, r) |
+ result = TBoolLiteral(parent, i) or
+ result = TNullLiteral(parent, i) or
+ result = TEnvVariable(parent, i) or
+ result = TAutomaticVariable(parent, i)
+ )
+ }
+
+ private predicate child(Raw::Ast parent, ChildIndex i, Child child, Raw::VarAccess va) {
+ exists(string s |
+ parent.getChild(toRawChildIndex(i)) = va and
+ va.getUserPath().toLowerCase() = s
+ |
+ s = "true" and
+ child = SynthChild(BoolLiteralKind(true))
+ or
+ s = "false" and
+ child = SynthChild(BoolLiteralKind(false))
+ or
+ s = "null" and
+ child = SynthChild(NullLiteralKind())
+ or
+ Raw::isEnvVariableAccess(va, s) and
+ child = SynthChild(EnvVariableKind(s))
+ or
+ Raw::isAutomaticVariableAccess(va, s) and
+ child = SynthChild(AutomaticVariableKind(s))
+ )
+ }
+
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ this.child(parent, i, child, _)
+ }
+
+ final override predicate booleanValue(BoolLiteral b, boolean value) {
+ exists(Raw::Ast parent, ChildIndex i |
+ b = TBoolLiteral(parent, i) and
+ this.child(parent, i, SynthChild(BoolLiteralKind(value)))
+ )
+ }
+
+ final override predicate envVariableName(EnvVariable var, string name) {
+ exists(Raw::Ast parent, ChildIndex i |
+ var = TEnvVariable(parent, i) and
+ this.child(parent, i, SynthChild(EnvVariableKind(name)))
+ )
+ }
+
+ final override predicate automaticVariableName(AutomaticVariable var, string name) {
+ exists(Raw::Ast parent, ChildIndex i |
+ var = TAutomaticVariable(parent, i) and
+ this.child(parent, i, SynthChild(AutomaticVariableKind(name)))
+ )
+ }
+
+ final override Location getLocation(Ast n) {
+ exists(Raw::VarAccess va |
+ this.child(_, _, _, va) and
+ n = getResultAst(va) and
+ result = va.getLocation()
+ )
+ }
+ }
+}
+
+/**
+ * Synthesize variable accesses for pipeline iterators inside a process block.
+ */
+private module IteratorAccessSynth {
+ private class PipelineOrPipelineByPropertyNameIteratorVariable extends VariableSynth {
+ PipelineOrPipelineByPropertyNameIteratorVariable() {
+ this instanceof PipelineIteratorVariable
+ or
+ this instanceof PipelineByPropertyNameIteratorVariable
+ }
+
+ string getPropertyName() {
+ result = this.(PipelineByPropertyNameIteratorVariable).getPropertyName()
+ }
+
+ predicate isPipelineIterator() { this instanceof PipelineIteratorVariable }
+ }
+
+ bindingset[pb, v]
+ private string getAPipelineIteratorName(
+ Raw::ProcessBlock pb, PipelineOrPipelineByPropertyNameIteratorVariable v
+ ) {
+ v.isPipelineIterator() and
+ (
+ result = "_"
+ or
+ // or
+ // result = "psitem" // TODO: This is also an automatic variable
+ result = pb.getScriptBlock().getParamBlock().getPipelineParameter().getName().toLowerCase()
+ )
+ or
+ // TODO: We could join on something other than the string if we wanted (i.e., the raw parameter).
+ v.getPropertyName().toLowerCase() = result and
+ result =
+ pb.getScriptBlock()
+ .getParamBlock()
+ .getAPipelineByPropertyNameParameter()
+ .getName()
+ .toLowerCase()
+ }
+
+ private class IteratorAccessSynth extends Synthesis {
+ private predicate expr(Raw::Ast rawParent, ChildIndex i, Raw::VarAccess va, Child child) {
+ rawParent.getChild(toRawChildIndex(i)) = va and
+ child = SynthChild(VarAccessSynthKind(this.varAccess(va)))
+ }
+
+ private predicate stmt(Raw::Ast rawParent, ChildIndex i, Raw::CmdExpr cmdExpr, Child child) {
+ rawParent.getChild(toRawChildIndex(i)) = cmdExpr and
+ not mustHaveExprChild(rawParent, cmdExpr) and
+ child = SynthChild(ExprStmtKind())
+ }
+
+ private PipelineOrPipelineByPropertyNameIteratorVariable varAccess(Raw::VarAccess va) {
+ exists(Raw::ProcessBlock pb |
+ pb = va.getParent+() and
+ result = TVariableSynth(pb, _) and
+ va.getUserPath().toLowerCase() = getAPipelineIteratorName(pb, result)
+ )
+ }
+
+ override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
+ this.expr(parent, i, _, child)
+ or
+ this.stmt(parent, i, _, child)
+ or
+ exists(Raw::ProcessBlock pb | parent = pb |
+ i = PipelineIteratorVar() and
+ child = SynthChild(VarSynthKind(PipelineIteratorKind()))
+ or
+ exists(Raw::Parameter p |
+ p = pb.getScriptBlock().getParamBlock().getAPipelineByPropertyNameParameter() and
+ child = SynthChild(VarSynthKind(PipelineByPropertyNameIteratorKind(p.getName()))) and
+ i = PipelineByPropertyNameIteratorVar(p)
+ )
+ )
+ }
+
+ override predicate exprStmtExpr(ExprStmt e, Expr expr) {
+ exists(Raw::Ast p, Raw::VarAccess va, Raw::CmdExpr cmdExpr, ChildIndex i1, ChildIndex i2 |
+ this.stmt(p, i1, _, _) and
+ this.expr(cmdExpr, i2, va, _) and
+ e = TExprStmtSynth(p, i1) and
+ expr = TVarAccessSynth(cmdExpr, i2, this.varAccess(va))
+ )
+ }
+
+ final override Expr getResultAstImpl(Raw::Ast r) {
+ exists(Raw::Ast parent, ChildIndex i | this.expr(parent, i, r, _) |
+ result = TVarAccessSynth(parent, i, this.varAccess(r))
+ )
+ }
+
+ override predicate variableSynthName(VariableSynth v, string name) {
+ v = TVariableSynth(_, PipelineIteratorVar()) and
+ name = "__pipeline_iterator"
+ or
+ exists(Raw::PipelineByPropertyNameParameter p |
+ v = TVariableSynth(_, PipelineByPropertyNameIteratorVar(p)) and
+ name = "__pipeline_iterator for " + p.getName()
+ )
+ }
+
+ final override Location getLocation(Ast n) {
+ exists(Raw::Ast parent, ChildIndex i, Raw::CmdExpr cmdExpr |
+ this.stmt(parent, i, cmdExpr, _) and
+ n = TExprStmtSynth(parent, i) and
+ result = cmdExpr.getLocation()
+ )
+ or
+ exists(Raw::Ast parent |
+ n = TVariableSynth(parent, _) and
+ result = parent.getLocation()
+ )
+ }
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TAst.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TAst.qll
new file mode 100644
index 000000000000..6bc4bf7a8bdb
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TAst.qll
@@ -0,0 +1,328 @@
+private import Raw.Raw as Raw
+private import Location
+private import Ast as Ast
+private import Synthesis
+private import Expr
+private import Internal::Private
+private import Internal::Public
+
+private predicate mkSynthChild(SynthKind kind, Raw::Ast parent, ChildIndex i) {
+ any(Synthesis s).child(parent, i, SynthChild(kind))
+}
+
+string variableNameInScope(Raw::Ast n, Scope::Range scope) {
+ scope = Raw::scopeOf(n) and
+ (
+ result = n.(Raw::VarAccess).getUserPath() and
+ not scope.getAParameter().(Raw::PipelineByPropertyNameParameter).getName() = result and
+ not result.toLowerCase() = ["_", "this", "false", "true", "null"] and
+ not parameter(_, n, _, _) and
+ not Raw::isEnvVariableAccess(n, _) and
+ not Raw::isAutomaticVariableAccess(n, _)
+ or
+ any(Synthesis s).explicitAssignment(n, result, _)
+ or
+ any(Synthesis s).implicitAssignment(n, result)
+ )
+}
+
+private predicate scopeAssigns(Scope::Range scope, string name, Raw::Ast n) {
+ (explicitAssignment(n, _) or implicitAssignment(n)) and
+ name = variableNameInScope(n, scope)
+}
+
+private predicate scopeDefinesParameterVariable(Scope::Range scope, string name) {
+ exists(Raw::Parameter p |
+ any(Synthesis s).implicitAssignment(p, name) and
+ p.getScope() = scope
+ )
+}
+
+private predicate inherits(Scope::Range scope, string name, Scope::Range outer) {
+ not scopeDefinesParameterVariable(scope, name) and
+ (
+ outer = scope.getOuterScope() and
+ (
+ scopeDefinesParameterVariable(outer, name)
+ or
+ exists(Raw::Ast n |
+ scopeAssigns(outer, name, n) and
+ n.getLocation().strictlyBefore(scope.getLocation())
+ )
+ )
+ or
+ inherits(scope.getOuterScope(), name, outer)
+ )
+}
+
+pragma[nomagic]
+private predicate hasScopeAndName(VariableImpl variable, Scope::Range scope, string name) {
+ variable.getNameImpl() = name and
+ scope = variable.getDeclaringScopeImpl()
+}
+
+private predicate access(Raw::VarAccess va, VariableImpl v) {
+ exists(string name, Scope::Range scope |
+ pragma[only_bind_into](name) = variableNameInScope(va, scope)
+ |
+ hasScopeAndName(v, scope, name)
+ or
+ exists(Scope::Range declScope |
+ hasScopeAndName(v, declScope, pragma[only_bind_into](name)) and
+ inherits(scope, name, declScope)
+ )
+ )
+}
+
+cached
+private module Cached {
+ private predicate excludeStringConstExpr(Raw::StringConstExpr e) {
+ // i.e., "Node" or "Script"
+ dynamic_keyword_statement_command_elements(_, 0, e)
+ }
+
+ cached
+ newtype TAst =
+ TAttributedExpr(Raw::AttributedExpr a) or
+ TArrayExpr(Raw::ArrayExpr e) or
+ TArrayLiteral(Raw::ArrayLiteral lit) or
+ TAssignStmt(Raw::AssignStmt s) or
+ TAttribute(Raw::Attribute a) or
+ TBinaryExpr(Raw::BinaryExpr bin) or
+ TBreakStmt(Raw::BreakStmt br) or
+ TCatchClause(Raw::CatchClause cc) or
+ TCmd(Raw::Cmd c) or
+ TExprStmtSynth(Raw::Ast parent, ChildIndex i) { mkSynthChild(ExprStmtKind(), parent, i) } or
+ TTopLevelFunction(Raw::TopLevelScriptBlock scriptBlock) or
+ TFunctionSynth(Raw::Ast parent, ChildIndex i) { mkSynthChild(FunctionSynthKind(), parent, i) } or
+ TConfiguration(Raw::Configuration c) or
+ TConstExpr(Raw::ConstExpr c) or
+ TContinueStmt(Raw::ContinueStmt c) or
+ TConvertExpr(Raw::ConvertExpr c) or
+ TDataStmt(Raw::DataStmt d) or
+ TDoUntilStmt(Raw::DoUntilStmt d) or
+ TDoWhileStmt(Raw::DoWhileStmt d) or
+ TDynamicStmt(Raw::DynamicStmt d) or
+ TErrorExpr(Raw::ErrorExpr e) or
+ TErrorStmt(Raw::ErrorStmt e) or
+ TExitStmt(Raw::ExitStmt e) or
+ TExpandableStringExpr(Raw::ExpandableStringExpr e) or
+ TFunctionDefinitionStmt(Raw::FunctionDefinitionStmt f) { not excludeFunctionDefinitionStmt(f) } or
+ TForEachStmt(Raw::ForEachStmt f) or
+ TForStmt(Raw::ForStmt f) or
+ THashTableExpr(Raw::HashTableExpr h) or
+ TIf(Raw::IfStmt i) or
+ TIndexExpr(Raw::IndexExpr i) or
+ TInvokeMemberExpr(Raw::InvokeMemberExpr i) or
+ TMethod(Raw::Method m) or
+ TMemberExpr(Raw::MemberExpr m) or
+ TNamedAttributeArgument(Raw::NamedAttributeArgument n) or
+ TNamedBlock(Raw::NamedBlock n) or
+ TParenExpr(Raw::ParenExpr p) or
+ TPipeline(Raw::Pipeline p) or
+ TPipelineChain(Raw::PipelineChain p) or
+ TPropertyMember(Raw::PropertyMember p) or
+ TRedirection(Raw::Redirection r) or
+ TReturnStmt(Raw::ReturnStmt r) or
+ TScriptBlock(Raw::ScriptBlock s) or
+ TScriptBlockExpr(Raw::ScriptBlockExpr s) or
+ TExpandableSubExpr(Raw::ExpandableSubExpr e) or
+ TStmtBlock(Raw::StmtBlock s) or
+ TStringConstExpr(Raw::StringConstExpr s) { not excludeStringConstExpr(s) } or
+ TSwitchStmt(Raw::SwitchStmt s) or
+ TConditionalExpr(Raw::ConditionalExpr t) or
+ TThrowStmt(Raw::ThrowStmt t) or
+ TTrapStmt(Raw::TrapStmt t) or
+ TThisExprReal(Raw::ThisAccess t) or
+ TTryStmt(Raw::TryStmt t) or
+ TTypeDefinitionStmt(Raw::TypeStmt t) or
+ TTypeSynth(Raw::Ast parent, ChildIndex i) { mkSynthChild(TypeSynthKind(), parent, i) } or
+ TTypeConstraint(Raw::TypeConstraint t) or
+ TUnaryExpr(Raw::UnaryExpr u) or
+ TUsingStmt(Raw::UsingStmt u) or
+ TVariableReal(Scope::Range scope, string name, Raw::Ast n) {
+ not n instanceof Raw::Parameter and // we synthesize all parameters
+ n =
+ min(Raw::Ast other |
+ scopeAssigns(scope, name, other)
+ |
+ other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
+ )
+ } or
+ TVariableSynth(Raw::Ast scope, ChildIndex i) { mkSynthChild(VarSynthKind(_), scope, i) } or
+ TVarAccessReal(Raw::VarAccess va, Variable v) { access(va, v) } or
+ TVarAccessSynth(Raw::Ast parent, ChildIndex i, Variable v) {
+ mkSynthChild(VarAccessRealKind(v), parent, i)
+ or
+ mkSynthChild(VarAccessSynthKind(v), parent, i)
+ } or
+ TWhileStmt(Raw::WhileStmt w) or
+ TTypeNameExpr(Raw::TypeNameExpr t) or
+ TUsingExpr(Raw::UsingExpr u) or
+ TBoolLiteral(Raw::Ast parent, ChildIndex i) { mkSynthChild(BoolLiteralKind(_), parent, i) } or
+ TNullLiteral(Raw::Ast parent, ChildIndex i) { mkSynthChild(NullLiteralKind(), parent, i) } or
+ TEnvVariable(Raw::Ast parent, ChildIndex i) { mkSynthChild(EnvVariableKind(_), parent, i) } or
+ TAutomaticVariable(Raw::Ast parent, ChildIndex i) {
+ mkSynthChild(AutomaticVariableKind(_), parent, i)
+ }
+
+ class TAstReal =
+ TArrayExpr or TArrayLiteral or TAssignStmt or TAttribute or TOperation or TBreakStmt or
+ TCatchClause or TCmd or TConfiguration or TConstExpr or TContinueStmt or TConvertExpr or
+ TDataStmt or TDoUntilStmt or TDoWhileStmt or TDynamicStmt or TErrorExpr or TErrorStmt or
+ TExitStmt or TExpandableStringExpr or TForEachStmt or TForStmt or TGotoStmt or
+ THashTableExpr or TIf or TIndexExpr or TInvokeMemberExpr or TMemberExpr or
+ TNamedAttributeArgument or TNamedBlock or TPipeline or TPipelineChain or TPropertyMember or
+ TRedirection or TReturnStmt or TScriptBlock or TScriptBlockExpr or TStmtBlock or
+ TStringConstExpr or TSwitchStmt or TConditionalExpr or TThrowStmt or TTrapStmt or
+ TTryStmt or TTypeDefinitionStmt or TTypeConstraint or TUsingStmt or TVarAccessReal or
+ TWhileStmt or TFunctionDefinitionStmt or TExpandableSubExpr or TMethod or TTypeNameExpr or
+ TAttributedExpr or TUsingExpr or TThisExprReal or TParenExpr or TVariableReal;
+
+ class TAstSynth =
+ TExprStmtSynth or TFunctionSynth or TBoolLiteral or TNullLiteral or TVarAccessSynth or
+ TEnvVariable or TTypeSynth or TAutomaticVariable or TVariableSynth;
+
+ class TExpr =
+ TArrayExpr or TArrayLiteral or TOperation or TConstExpr or TConvertExpr or TErrorExpr or
+ THashTableExpr or TIndexExpr or TInvokeMemberExpr or TCmd or TMemberExpr or TPipeline or
+ TPipelineChain or TStringConstExpr or TConditionalExpr or TVarAccess or
+ TExpandableStringExpr or TScriptBlockExpr or TExpandableSubExpr or TTypeNameExpr or
+ TUsingExpr or TAttributedExpr or TIf or TBoolLiteral or TNullLiteral or TThisExpr or
+ TEnvVariable or TAutomaticVariable or TParenExpr;
+
+ class TStmt =
+ TAssignStmt or TBreakStmt or TContinueStmt or TDataStmt or TDoUntilStmt or TDoWhileStmt or
+ TDynamicStmt or TErrorStmt or TExitStmt or TForEachStmt or TForStmt or TGotoStmt or
+ TReturnStmt or TStmtBlock or TSwitchStmt or TThrowStmt or TTrapStmt or TTryStmt or
+ TUsingStmt or TWhileStmt or TConfiguration or TTypeDefinitionStmt or
+ TFunctionDefinitionStmt or TExprStmt;
+
+ class TType = TTypeSynth;
+
+ class TOperation = TBinaryExpr or TUnaryExpr;
+
+ class TMember = TPropertyMember or TMethod;
+
+ class TExprStmt = TExprStmtSynth;
+
+ class TAttributeBase = TAttribute or TTypeConstraint;
+
+ class TFunction = TFunctionSynth or TTopLevelFunction;
+
+ class TFunctionBase = TFunction or TMethod;
+
+ class TAttributedExprBase = TAttributedExpr or TConvertExpr;
+
+ class TCallExpr = TCmd or TInvokeMemberExpr;
+
+ class TLoopStmt = TDoUntilStmt or TDoWhileStmt or TForEachStmt or TForStmt or TWhileStmt;
+
+ class TVarAccess = TVarAccessReal or TVarAccessSynth;
+
+ class TLiteral = TBoolLiteral or TNullLiteral;
+
+ class TGotoStmt = TContinueStmt or TBreakStmt;
+
+ class TThisExpr = TThisExprReal;
+
+ cached
+ Raw::Ast toRaw(TAstReal n) {
+ n = TArrayExpr(result) or
+ n = TArrayLiteral(result) or
+ n = TAssignStmt(result) or
+ n = TAttribute(result) or
+ n = TBinaryExpr(result) or
+ n = TBreakStmt(result) or
+ n = TCatchClause(result) or
+ n = TCmd(result) or
+ n = TConfiguration(result) or
+ n = TConstExpr(result) or
+ n = TContinueStmt(result) or
+ n = TConvertExpr(result) or
+ n = TDataStmt(result) or
+ n = TDoUntilStmt(result) or
+ n = TDoWhileStmt(result) or
+ n = TDynamicStmt(result) or
+ n = TErrorExpr(result) or
+ n = TErrorStmt(result) or
+ n = TExitStmt(result) or
+ n = TExpandableStringExpr(result) or
+ n = TForEachStmt(result) or
+ n = TForStmt(result) or
+ n = THashTableExpr(result) or
+ n = TIf(result) or
+ n = TIndexExpr(result) or
+ n = TInvokeMemberExpr(result) or
+ n = TMemberExpr(result) or
+ n = TNamedAttributeArgument(result) or
+ n = TNamedBlock(result) or
+ n = TPipeline(result) or
+ n = TParenExpr(result) or
+ n = TPipelineChain(result) or
+ n = TPropertyMember(result) or
+ n = TRedirection(result) or
+ n = TReturnStmt(result) or
+ n = TScriptBlock(result) or
+ n = TScriptBlockExpr(result) or
+ n = TStmtBlock(result) or
+ n = TStringConstExpr(result) or
+ n = TSwitchStmt(result) or
+ n = TConditionalExpr(result) or
+ n = TThrowStmt(result) or
+ n = TTrapStmt(result) or
+ n = TTryStmt(result) or
+ n = TTypeDefinitionStmt(result) or
+ n = TThisExprReal(result) or
+ n = TTypeConstraint(result) or
+ n = TUnaryExpr(result) or
+ n = TUsingStmt(result) or
+ n = TVarAccessReal(result, _) or
+ n = TWhileStmt(result) or
+ n = TFunctionDefinitionStmt(result) or
+ n = TExpandableSubExpr(result) or
+ n = TTypeNameExpr(result) or
+ n = TMethod(result) or
+ n = TAttributedExpr(result) or
+ n = TUsingExpr(result) or
+ n = TVariableReal(_, _, result)
+ }
+
+ cached
+ Raw::Ast toRawIncludingSynth(Ast::Ast n) {
+ result = toRaw(n)
+ or
+ not exists(toRaw(n)) and
+ exists(Raw::Ast parent |
+ synthChild(parent, _, n) and
+ result = parent
+ )
+ }
+
+ cached
+ TAstReal fromRaw(Raw::Ast a) { toRaw(result) = a }
+
+ cached
+ Ast::Ast getSynthChild(Raw::Ast parent, ChildIndex i) {
+ result = TExprStmtSynth(parent, i) or
+ result = TFunctionSynth(parent, i) or
+ result = TBoolLiteral(parent, i) or
+ result = TNullLiteral(parent, i) or
+ result = TVarAccessSynth(parent, i, _) or
+ result = TEnvVariable(parent, i) or
+ result = TTypeSynth(parent, i) or
+ result = TAutomaticVariable(parent, i) or
+ result = TVariableSynth(parent, i)
+ }
+
+ cached
+ predicate synthChild(Raw::Ast parent, ChildIndex i, Ast::Ast child) {
+ child = getSynthChild(parent, i)
+ or
+ any(Synthesis s).child(parent, i, RealChildRef(child))
+ or
+ any(Synthesis s).child(parent, i, SynthChildRef(child))
+ }
+}
+
+import Cached
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TernaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TernaryExpression.qll
new file mode 100644
index 000000000000..022a3675dcd4
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TernaryExpression.qll
@@ -0,0 +1,55 @@
+private import AstImport
+
+class ConditionalExpr extends Expr, TConditionalExpr {
+ override string toString() { result = "...?...:..." }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = condExprCond() and
+ result = this.getCondition()
+ or
+ i = condExprTrue() and
+ result = this.getIfTrue()
+ or
+ i = condExprFalse() and
+ result = this.getIfFalse()
+ }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, condExprCond(), result)
+ or
+ not synthChild(r, condExprCond(), _) and
+ result = getResultAst(r.(Raw::ConditionalExpr).getCondition())
+ )
+ }
+
+ Expr getIfFalse() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, condExprFalse(), result)
+ or
+ not synthChild(r, condExprCond(), _) and
+ result = getResultAst(r.(Raw::ConditionalExpr).getIfFalse())
+ )
+ }
+
+ Expr getIfTrue() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, condExprTrue(), result)
+ or
+ not synthChild(r, condExprTrue(), _) and
+ result = getResultAst(r.(Raw::ConditionalExpr).getIfTrue())
+ )
+ }
+
+ Expr getBranch(boolean value) {
+ value = true and
+ result = this.getIfTrue()
+ or
+ value = false and
+ result = this.getIfFalse()
+ }
+
+ Expr getABranch() { result = this.getBranch(_) }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ThisExpr.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ThisExpr.qll
new file mode 100644
index 000000000000..e93e01f6399c
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ThisExpr.qll
@@ -0,0 +1,6 @@
+private import AstImport
+
+class ThisExpr extends Expr, TThisExpr {
+ final override string toString() { result = "this" }
+
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/ThrowStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/ThrowStmt.qll
new file mode 100644
index 000000000000..0b8ed0fe7c80
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/ThrowStmt.qll
@@ -0,0 +1,24 @@
+private import AstImport
+
+class ThrowStmt extends Stmt, TThrowStmt {
+ Expr getPipeline() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, throwStmtPipeline(), result)
+ or
+ not synthChild(r, throwStmtPipeline(), _) and
+ result = getResultAst(r.(Raw::ThrowStmt).getPipeline())
+ )
+ }
+
+ predicate hasPipeline() { exists(this.getPipeline()) }
+
+ override string toString() {
+ if this.hasPipeline() then result = "throw ..." else result = "throw"
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = throwStmtPipeline() and result = this.getPipeline()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TrapStatement.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TrapStatement.qll
new file mode 100644
index 000000000000..498522051253
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TrapStatement.qll
@@ -0,0 +1,33 @@
+private import AstImport
+
+class TrapStmt extends Stmt, TTrapStmt {
+ StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, trapStmtBody(), result)
+ or
+ not synthChild(r, trapStmtBody(), _) and
+ result = getResultAst(r.(Raw::TrapStmt).getBody())
+ )
+ }
+
+ TypeConstraint getTypeConstraint() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, trapStmtTypeConstraint(), result)
+ or
+ not synthChild(r, trapStmtTypeConstraint(), _) and
+ result = getResultAst(r.(Raw::TrapStmt).getTypeConstraint())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = trapStmtBody() and
+ result = this.getBody()
+ or
+ i = trapStmtTypeConstraint() and
+ result = this.getTypeConstraint()
+ }
+
+ override string toString() { result = "trap {...}" }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TryStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TryStmt.qll
new file mode 100644
index 000000000000..78d6dd8eba69
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TryStmt.qll
@@ -0,0 +1,52 @@
+private import AstImport
+
+class TryStmt extends Stmt, TTryStmt {
+ CatchClause getCatchClause(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = tryStmtCatchClause(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::TryStmt).getCatchClause(i))
+ )
+ }
+
+ CatchClause getACatchClause() { result = this.getCatchClause(_) }
+
+ /** ..., if any. */
+ StmtBlock getFinally() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, tryStmtFinally(), result)
+ or
+ not synthChild(r, tryStmtFinally(), _) and
+ result = getResultAst(r.(Raw::TryStmt).getFinally())
+ )
+ }
+
+ predicate hasFinally() { exists(this.getFinally()) }
+
+ StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, tryStmtBody(), result)
+ or
+ not synthChild(r, tryStmtBody(), _) and
+ result = getResultAst(r.(Raw::TryStmt).getBody())
+ )
+ }
+
+ override string toString() { result = "try {...}" }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = tryStmtBody() and
+ result = this.getBody()
+ or
+ exists(int index |
+ i = tryStmtCatchClause(index) and
+ result = this.getCatchClause(index)
+ )
+ or
+ i = tryStmtFinally() and
+ result = this.getFinally()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Type.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Type.qll
new file mode 100644
index 000000000000..5f7c739c9d43
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Type.qll
@@ -0,0 +1,38 @@
+private import AstImport
+
+class Type extends Ast, TTypeSynth {
+ override string toString() { result = this.getName() }
+
+ Member getMember(int i) { any(Synthesis s).typeMember(this, i, result) }
+
+ string getName() { any(Synthesis s).typeName(this, result) }
+
+ Member getAMember() { result = this.getMember(_) }
+
+ Method getMethod(string name) { result = this.getAMember() and result.getName() = name }
+
+ Method getAMethod() { result = this.getMethod(_) }
+
+ Constructor getAConstructor() {
+ result = this.getAMethod() and
+ result.getName() = this.getName()
+ }
+
+ TypeConstraint getBaseType(int i) { none() }
+
+ TypeConstraint getABaseType() { result = this.getBaseType(_) }
+
+ Type getASubtype() { none() }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ exists(int index |
+ i = typeMember(index) and
+ result = this.getMember(index)
+ or
+ i = typeStmtBaseType(index) and
+ result = this.getBaseType(index)
+ )
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeConstraint.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeConstraint.qll
new file mode 100644
index 000000000000..8085a3832aee
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeConstraint.qll
@@ -0,0 +1,7 @@
+private import AstImport
+
+class TypeConstraint extends Ast, TTypeConstraint {
+ string getName() { result = getRawAst(this).(Raw::TypeConstraint).getName() }
+
+ override string toString() { result = this.getName() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeDefinitionStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeDefinitionStmt.qll
new file mode 100644
index 000000000000..e630c2728141
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeDefinitionStmt.qll
@@ -0,0 +1,50 @@
+private import AstImport
+
+class TypeDefinitionStmt extends Stmt, TTypeDefinitionStmt {
+ string getName() { result = getRawAst(this).(Raw::TypeStmt).getName() }
+
+ override string toString() { result = this.getName() }
+
+ Member getMember(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = typeStmtMember(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::TypeStmt).getMember(i))
+ )
+ }
+
+ Member getAMember() { result = this.getMember(_) }
+
+ Method getMethod(string name) {
+ result = getResultAst(getRawAst(this).(Raw::TypeStmt).getMethod(name))
+ }
+
+ Method getAMethod() { result = this.getMethod(_) }
+
+ Constructor getAConstructor() {
+ result = this.getAMethod() and
+ result.getName() = this.getName()
+ }
+
+ TypeConstraint getBaseType(int i) {
+ exists(ChildIndex index, Raw::Ast r | index = typeStmtBaseType(i) and r = getRawAst(this) |
+ synthChild(r, index, result)
+ or
+ not synthChild(r, index, _) and
+ result = getResultAst(r.(Raw::TypeStmt).getBaseType(i))
+ )
+ }
+
+ TypeConstraint getABaseType() { result = this.getBaseType(_) }
+
+ TypeDefinitionStmt getASubtype() { result.getABaseType().getName() = this.getName() }
+
+ Type getType() { synthChild(getRawAst(this), typeDefType(), result) }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = typeDefType() and result = this.getType()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeExpression.qll
new file mode 100644
index 000000000000..73f1d1fe3714
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/TypeExpression.qll
@@ -0,0 +1,32 @@
+private import AstImport
+
+class TypeNameExpr extends Expr, TTypeNameExpr {
+ private predicate parseName(string namespace, string typename) {
+ exists(string fullName | fullName = this.getPossiblyQualifiedName() |
+ if fullName.matches("%.%")
+ then
+ namespace = fullName.regexpCapture("([a-zA-Z0-9\\.]+)\\.([a-zA-Z0-9]+)", 1) and
+ typename = fullName.regexpCapture("([a-zA-Z0-9\\.]+)\\.([a-zA-Z0-9]+)", 2)
+ else (
+ namespace = "" and
+ typename = fullName
+ )
+ )
+ }
+
+ string getName() { this.parseName(_, result) }
+
+ /** If any */
+ string getPossiblyQualifiedName() { result = getRawAst(this).(Raw::TypeNameExpr).getName() }
+
+ // TODO: What to do when System is omitted?
+ string getNamespace() { this.parseName(result, _) }
+
+ override string toString() { result = this.getName() }
+
+ predicate isQualified() { this.getNamespace() != "" }
+}
+
+class QualifiedTypeNameExpr extends TypeNameExpr {
+ QualifiedTypeNameExpr() { this.isQualified() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/UnaryExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/UnaryExpression.qll
similarity index 77%
rename from powershell/ql/lib/semmle/code/powershell/UnaryExpression.qll
rename to powershell/ql/lib/semmle/code/powershell/ast/internal/UnaryExpression.qll
index 6a42360d7dcf..860dddfc65b3 100644
--- a/powershell/ql/lib/semmle/code/powershell/UnaryExpression.qll
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/UnaryExpression.qll
@@ -1,11 +1,23 @@
-import powershell
+private import AstImport
-class UnaryExpr extends @unary_expression, Expr {
- override SourceLocation getLocation() { unary_expression_location(this, result) }
+class UnaryExpr extends Expr, TUnaryExpr {
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = unaryExprOp() and result = this.getOperand()
+ }
- int getKind() { unary_expression(this, _, result, _) }
+ /** INTERNAL: Do not use. */
+ int getKind() { result = getRawAst(this).(Raw::UnaryExpr).getKind() }
- Expr getOperand() { unary_expression(this, result, _, _) }
+ Expr getOperand() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, unaryExprOp(), result)
+ or
+ not synthChild(r, unaryExprOp(), _) and
+ result = getResultAst(r.(Raw::UnaryExpr).getOperand())
+ )
+ }
}
class NotExpr extends UnaryExpr {
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingExpression.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingExpression.qll
new file mode 100644
index 000000000000..32848d397dd1
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingExpression.qll
@@ -0,0 +1,21 @@
+private import AstImport
+
+class UsingExpr extends Expr, TUsingExpr {
+ override string toString() { result = "$using..." }
+
+ Expr getExpr() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, usingExprExpr(), result)
+ or
+ not synthChild(r, usingExprExpr(), _) and
+ result = getResultAst(r.(Raw::UsingExpr).getExpr())
+ )
+ }
+
+ override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = usingExprExpr() and
+ result = this.getExpr()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingStmt.qll
new file mode 100644
index 000000000000..d649560bcd98
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/UsingStmt.qll
@@ -0,0 +1,9 @@
+private import AstImport
+
+class UsingStmt extends Stmt, TUsingStmt {
+ override string toString() { result = "using ..." }
+
+ string getName() { result = getRawAst(this).(Raw::UsingStmt).getName() }
+
+ Scope getAnAffectedScope() { result.getEnclosingScope*() = this.getEnclosingScope() }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/Variable.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/Variable.qll
new file mode 100644
index 000000000000..27c2ac5063d7
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/Variable.qll
@@ -0,0 +1,181 @@
+private import TAst
+private import AstImport
+
+module Private {
+ class TVariable = TVariableReal or TVariableSynth;
+
+ class VariableImpl extends Ast, TVariable {
+ abstract string getNameImpl();
+
+ final override string toString() { result = this.getNameImpl() }
+
+ abstract Location getLocationImpl();
+
+ abstract Scope::Range getDeclaringScopeImpl();
+ }
+
+ class VariableReal extends VariableImpl, TVariableReal {
+ Scope::Range scope;
+ string name;
+ Raw::Ast n;
+
+ VariableReal() { this = TVariableReal(scope, name, n) }
+
+ override string getNameImpl() { result = name }
+
+ override Location getLocationImpl() { result = n.getLocation() }
+
+ final override Scope::Range getDeclaringScopeImpl() { result = scope }
+
+ predicate isParameter(Raw::Parameter p) { n = p }
+ }
+
+ class VariableSynth extends VariableImpl, TVariableSynth {
+ Raw::Ast scope;
+ ChildIndex i;
+
+ VariableSynth() { this = TVariableSynth(scope, i) }
+
+ override string getNameImpl() { any(Synthesis s).variableSynthName(this, result) }
+
+ override Location getLocationImpl() { result = scope.getLocation() }
+
+ override Scope::Range getDeclaringScopeImpl() { result = scope }
+ }
+
+ class ParameterImpl extends VariableSynth {
+ ParameterImpl() {
+ i instanceof FunParam or i instanceof PipelineParamVar or i instanceof ThisVar
+ }
+ }
+
+ class ThisParameterImpl extends VariableSynth {
+ override ThisVar i;
+ }
+
+ class PipelineVariableImpl extends ParameterImpl {
+ override PipelineParamVar i;
+
+ ScriptBlock getScriptBlock() { this = TVariableSynth(getRawAst(result), _) }
+ }
+
+ class PipelineIteratorVariableImpl extends VariableSynth {
+ override PipelineIteratorVar i;
+
+ ProcessBlock getProcessBlock() { this = TVariableSynth(getRawAst(result), _) }
+ }
+
+ class PipelineByPropertyNameIteratorVariableImpl extends VariableSynth {
+ override PipelineByPropertyNameIteratorVar i;
+
+ ProcessBlock getProcessBlock() { this = TVariableSynth(getRawAst(result), _) }
+
+ /**
+ * Note: No result if this is not a pipeline-by-property-name.
+ */
+ string getPropertyName() {
+ exists(Raw::PipelineByPropertyNameParameter p |
+ i = PipelineByPropertyNameIteratorVar(p) and
+ result = p.getName()
+ )
+ }
+
+ PipelineByPropertyNameParameter getParameter() {
+ exists(Raw::PipelineByPropertyNameParameter p |
+ i = PipelineByPropertyNameIteratorVar(p) and
+ p.getScriptBlock() = getRawAst(result.getEnclosingFunction().getBody()) and
+ p.getName() = result.getName()
+ )
+ }
+ }
+
+ abstract class VarAccessImpl extends Expr, TVarAccess {
+ abstract VariableImpl getVariableImpl();
+ }
+
+ class VarAccessReal extends VarAccessImpl, TVarAccessReal {
+ Raw::VarAccess va;
+ Variable v;
+
+ VarAccessReal() { this = TVarAccessReal(va, v) }
+
+ final override Variable getVariableImpl() { result = v }
+
+ final override string toString() { result = v.getName() }
+ }
+
+ class VarAccessSynth extends VarAccessImpl, TVarAccessSynth {
+ Raw::Ast parent;
+ ChildIndex i;
+ Variable v;
+
+ VarAccessSynth() { this = TVarAccessSynth(parent, i, v) }
+
+ final override Variable getVariableImpl() { result = v }
+
+ final override string toString() { result = v.getName() }
+
+ final override Location getLocation() { result = parent.getLocation() }
+ }
+
+ predicate explicitAssignment(Raw::Ast dest, Raw::Ast assignment) {
+ assignment.(Raw::AssignStmt).getLeftHandSide() = dest
+ or
+ any(Synthesis s).explicitAssignment(dest, _, assignment)
+ }
+
+ predicate implicitAssignment(Raw::Ast n) { any(Synthesis s).implicitAssignment(n, _) }
+}
+
+private import Private
+
+module Public {
+ class Variable extends Ast instanceof VariableImpl {
+ final string getName() { result = super.getNameImpl() }
+
+ final override string toString() { result = this.getName() }
+
+ final override Location getLocation() { result = super.getLocationImpl() }
+
+ Scope getDeclaringScope() { getRawAst(result) = super.getDeclaringScopeImpl() }
+
+ VarAccess getAnAccess() { result.getVariable() = this }
+ }
+
+ class VarAccess extends Expr instanceof VarAccessImpl {
+ Variable getVariable() { result = super.getVariableImpl() }
+
+ predicate isExplicitWrite(Ast assignment) {
+ explicitAssignment(getRawAst(this), getRawAst(assignment))
+ }
+
+ predicate isImplicitWrite() { implicitAssignment(getRawAst(this)) }
+ }
+
+ class VarWriteAccess extends VarAccess {
+ VarWriteAccess() { this.isExplicitWrite(_) or this.isImplicitWrite() }
+ }
+
+ class VarReadAccess extends VarAccess {
+ VarReadAccess() { not this instanceof VarWriteAccess }
+ }
+
+ class PipelineByPropertyNameIteratorVariable extends Variable instanceof PipelineByPropertyNameIteratorVariableImpl
+ {
+ ProcessBlock getProcessBlock() { result = super.getProcessBlock() }
+
+ string getPropertyName() { result = super.getPropertyName() }
+
+ PipelineByPropertyNameParameter getParameter() { result = super.getParameter() }
+ }
+
+ class PipelineVariable extends Variable instanceof PipelineVariableImpl {
+ ScriptBlock getScriptBlock() { result = super.getScriptBlock() }
+ }
+
+ class PipelineIteratorVariable extends Variable instanceof PipelineIteratorVariableImpl {
+ ProcessBlock getProcessBlock() { result = super.getProcessBlock() }
+ }
+}
+
+import Public
diff --git a/powershell/ql/lib/semmle/code/powershell/ast/internal/WhileStmt.qll b/powershell/ql/lib/semmle/code/powershell/ast/internal/WhileStmt.qll
new file mode 100644
index 000000000000..d8817a6b0371
--- /dev/null
+++ b/powershell/ql/lib/semmle/code/powershell/ast/internal/WhileStmt.qll
@@ -0,0 +1,33 @@
+private import AstImport
+
+class WhileStmt extends LoopStmt, TWhileStmt {
+ override string toString() { result = "while(...) {...}" }
+
+ Expr getCondition() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, whileStmtCond(), result)
+ or
+ not synthChild(r, whileStmtCond(), _) and
+ result = getResultAst(r.(Raw::WhileStmt).getCondition())
+ )
+ }
+
+ final override StmtBlock getBody() {
+ exists(Raw::Ast r | r = getRawAst(this) |
+ synthChild(r, whileStmtBody(), result)
+ or
+ not synthChild(r, whileStmtBody(), _) and
+ result = getResultAst(r.(Raw::WhileStmt).getBody())
+ )
+ }
+
+ final override Ast getChild(ChildIndex i) {
+ result = super.getChild(i)
+ or
+ i = whileStmtCond() and
+ result = this.getCondition()
+ or
+ i = whileStmtBody() and
+ result = this.getBody()
+ }
+}
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll
index 8c8efcbb42d0..809ef64f8724 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll
+++ b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll
@@ -127,433 +127,849 @@ abstract private class NonExprChildMapping extends ChildMapping {
}
}
-abstract private class AbstractCallCfgNode extends AstCfgNode {
- override string getAPrimaryQlClass() { result = "CfgCall" }
+private class AttributeBaseChildMapping extends NonExprChildMapping, AttributeBase {
+ override predicate relevantChild(Ast child) { none() }
+}
+
+class AttributeBaseCfgNode extends AstCfgNode {
+ AttributeBaseCfgNode() { attr = this.getAstNode() }
- /** Holds if this call invokes a function with the name `name`. */
- final predicate hasName(string name) { this.getName() = name }
+ override string getAPrimaryQlClass() { result = "AttributeBaseCfgNode" }
+
+ AttributeBaseChildMapping attr;
+}
- /** Gets the name of the function that is invoked by this call. */
- abstract string getName();
+private class AttributeChildMapping extends AttributeBaseChildMapping, Attribute {
+ override predicate relevantChild(Ast child) {
+ this.relevantChild(child)
+ or
+ child = this.getANamedArgument()
+ or
+ child = this.getAPositionalArgument()
+ }
+}
- /** Gets the qualifier of this call, if any. */
- ExprCfgNode getQualifier() { none() }
+private class NamedAttributeArgumentChildMapping extends NonExprChildMapping, NamedAttributeArgument
+{
+ override predicate relevantChild(Ast child) { child = this.getValue() }
+}
- /** Gets the i'th argument to this call. */
- abstract ExprCfgNode getArgument(int i);
+class NamedAttributeArgumentCfgNode extends AstCfgNode {
+ NamedAttributeArgumentCfgNode() { attr = this.getAstNode() }
- /** Gets the i'th positional argument to this call. */
- abstract ExprCfgNode getPositionalArgument(int i);
+ override string getAPrimaryQlClass() { result = "NamedAttributeArgumentCfgNode" }
- /** Gets the argument with the name `name`, if any. */
- abstract ExprCfgNode getNamedArgument(string name);
+ NamedAttributeArgumentChildMapping attr;
- /**
- * Gets any argument of this call.
- *
- * Note that this predicate doesn't get the pipeline argument, if any.
- */
- abstract ExprCfgNode getAnArgument();
+ NamedAttributeArgument getAttr() { result = attr }
- /**
- * Gets the expression that provides the call target of this call, if any.
- */
- abstract ExprCfgNode getCommand();
+ ExprCfgNode getValue() { attr.hasCfgChild(attr.getValue(), this, result) }
+
+ string getName() { result = attr.getName() }
+}
+
+class AttributeCfgNode extends AttributeBaseCfgNode {
+ override string getAPrimaryQlClass() { result = "AttributeCfgNode" }
+
+ override AttributeChildMapping attr;
+
+ NamedAttributeArgumentCfgNode getNamedArgument(int i) {
+ attr.hasCfgChild(attr.getNamedArgument(i), this, result)
+ }
+
+ ExprCfgNode getPositionalArgument(int i) {
+ attr.hasCfgChild(attr.getPositionalArgument(i), this, result)
+ }
+}
+
+private class ScriptBlockChildMapping extends NonExprChildMapping, ScriptBlock {
+ override predicate relevantChild(Ast child) {
+ child = this.getProcessBlock()
+ or
+ child = this.getBeginBlock()
+ or
+ child = this.getEndBlock()
+ or
+ child = this.getDynamicBlock()
+ or
+ child = this.getAnAttribute()
+ or
+ child = this.getAParameter()
+ }
+}
- int getNumberOfArguments() { result = count(this.getAnArgument()) }
+private class ParameterChildMapping extends NonExprChildMapping, Parameter {
+ override predicate relevantChild(Ast child) {
+ child = this.getAnAttribute() or child = this.getDefaultValue()
+ }
}
-final class CallCfgNode = AbstractCallCfgNode;
+class ParameterCfgNode extends AstCfgNode {
+ ParameterCfgNode() { param = this.getAstNode() }
+
+ override string getAPrimaryQlClass() { result = "ParameterCfgNode" }
-class ObjectCreationCfgNode extends CallCfgNode {
- ObjectCreation objectCreation;
+ ParameterChildMapping param;
- ObjectCreationCfgNode() { this.getAstNode() = objectCreation }
+ Parameter getParameter() { result = param }
- ObjectCreation getObjectCreation() { result = objectCreation }
+ ExprCfgNode getDefaultValue() { param.hasCfgChild(param.getDefaultValue(), this, result) }
- Type getConstructedType() { result = objectCreation.getConstructedType() }
+ AttributeCfgNode getAttribute(int i) { param.hasCfgChild(param.getAttribute(i), this, result) }
- string getConstructedTypeName() { result = objectCreation.getConstructedTypeName() }
+ AttributeCfgNode getAnAttribute() { result = this.getAttribute(_) }
+}
+
+class ScriptBlockCfgNode extends AstCfgNode {
+ ScriptBlockCfgNode() { block = this.getAstNode() }
+
+ override string getAPrimaryQlClass() { result = "ScriptBlockCfgNode" }
+
+ ScriptBlockChildMapping block;
+
+ ScriptBlock getBlock() { result = block }
+
+ ProcessBlockCfgNode getProcessBlock() { block.hasCfgChild(block.getProcessBlock(), this, result) }
+
+ NamedBlockCfgNode getBeginBlock() { block.hasCfgChild(block.getBeginBlock(), this, result) }
+
+ NamedBlockCfgNode getEndBlock() { block.hasCfgChild(block.getEndBlock(), this, result) }
+
+ NamedBlockCfgNode getDynamicBlock() { block.hasCfgChild(block.getDynamicBlock(), this, result) }
+
+ AttributeCfgNode getAttribute(int i) { block.hasCfgChild(block.getAttribute(i), this, result) }
+
+ AttributeCfgNode getAnAttribute() { result = this.getAttribute(_) }
+
+ ParameterCfgNode getParameter(int i) { block.hasCfgChild(block.getParameter(i), this, result) }
+
+ ParameterCfgNode getAParameter() { result = this.getParameter(_) }
}
private class NamedBlockChildMapping extends NonExprChildMapping, NamedBlock {
- override predicate relevantChild(Ast n) { n = this.getAStmt() } // TODO: Handle getATrap
+ override predicate relevantChild(Ast child) {
+ child = this.getAStmt() or child = this.getATrapStmt()
+ }
}
class NamedBlockCfgNode extends AstCfgNode {
- NamedBlockChildMapping block;
+ NamedBlockCfgNode() { block = this.getAstNode() }
- NamedBlockCfgNode() { this.getAstNode() = block }
+ override string getAPrimaryQlClass() { result = "NamedBlockCfgNode" }
+
+ NamedBlockChildMapping block;
NamedBlock getBlock() { result = block }
StmtCfgNode getStmt(int i) { block.hasCfgChild(block.getStmt(i), this, result) }
- StmtCfgNode getAStmt() { block.hasCfgChild(block.getAStmt(), this, result) }
+ StmtCfgNode getAStmt() { result = this.getStmt(_) }
+
+ StmtNodes::TrapStmtCfgNode getTrapStmt(int i) {
+ block.hasCfgChild(block.getTrapStmt(i), this, result)
+ }
+
+ StmtNodes::TrapStmtCfgNode getATrapStmt() { result = this.getTrapStmt(_) }
}
private class ProcessBlockChildMapping extends NamedBlockChildMapping, ProcessBlock { }
class ProcessBlockCfgNode extends NamedBlockCfgNode {
+ override string getAPrimaryQlClass() { result = "ProcessBlockCfgNode" }
+
override ProcessBlockChildMapping block;
override ProcessBlock getBlock() { result = block }
- PipelineParameter getPipelineParameter() { result = block.getPipelineParameter() }
-
- PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
- result = block.getAPipelineByPropertyNameParameter()
- }
+ ScriptBlockCfgNode getScriptBlock() { result.getProcessBlock() = this }
}
-private class StmtBlockChildMapping extends NonExprChildMapping, StmtBlock {
- override predicate relevantChild(Ast n) { n = this.getAStmt() or n = this.getAnElement() }
-}
+module ExprNodes {
+ private class ArrayExprChildMapping extends ExprChildMapping, ArrayExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getAnExpr()
+ or
+ child = this.getStmtBlock()
+ }
+ }
-class StmtBlockCfgNode extends AstCfgNode {
- StmtBlockChildMapping block;
+ class ArrayExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ArrayExprCfgNode" }
- StmtBlockCfgNode() { this.getAstNode() = block }
+ override ArrayExprChildMapping e;
- StmtBlock getBlock() { result = block }
+ override ArrayExpr getExpr() { result = e }
- StmtCfgNode getStmt(int i) { block.hasCfgChild(block.getStmt(i), this, result) }
+ ExprCfgNode getExpr(int i) { e.hasCfgChild(e.getExpr(i), this, result) }
- StmtCfgNode getAStmt() { block.hasCfgChild(block.getAStmt(), this, result) }
+ ExprCfgNode getAnExpr() { result = this.getExpr(_) }
- /** Gets an AST element that may be returned from this `StmtBlockCfgNode`. */
- AstCfgNode getAnElement() { block.hasCfgChild(block.getAnElement(), this, result) }
-}
+ StmtCfgNode getStmtBlock() { e.hasCfgChild(e.getStmtBlock(), this, result) }
+ }
-/** Provides classes for control-flow nodes that wrap AST expressions. */
-module ExprNodes {
- private class VarAccessChildMapping extends ExprChildMapping, VarAccess {
- override predicate relevantChild(Ast n) { none() }
+ private class ArrayLiteralChildMapping extends ExprChildMapping, ArrayLiteral {
+ override predicate relevantChild(Ast child) { child = this.getAnExpr() }
}
- class VarAccessCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "VarAccessCfgNode" }
+ class ArrayLiteralCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ArrayLiteralCfgNode" }
- override VarAccessChildMapping e;
+ override ArrayLiteralChildMapping e;
- override VarAccess getExpr() { result = super.getExpr() }
+ override ArrayLiteral getExpr() { result = e }
- Variable getVariable() { result = e.getVariable() }
+ ExprCfgNode getExpr(int i) { e.hasCfgChild(e.getExpr(i), this, result) }
+
+ ExprCfgNode getAnExpr() { result = this.getExpr(_) }
}
- private class VarReadAccessChildMapping extends VarAccessChildMapping, VarReadAccess { }
+ private class ParenExprChildMapping extends ExprChildMapping, ParenExpr {
+ override predicate relevantChild(Ast child) { child = this.getExpr() }
+ }
- class VarReadAccessCfgNode extends VarAccessCfgNode {
- override string getAPrimaryQlClass() { result = "VarReadAccessCfgNode" }
+ class ParenExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ParenExprCfgNode" }
- override VarReadAccessChildMapping e;
+ override ParenExprChildMapping e;
+
+ override ParenExpr getExpr() { result = e }
- override VarReadAccess getExpr() { result = super.getExpr() }
+ ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
}
- private class VarWriteAccessChildMapping extends VarAccessChildMapping, VarWriteAccess { }
+ private class BinaryExprChildMapping extends ExprChildMapping, BinaryExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getLeft()
+ or
+ child = this.getRight()
+ }
+ }
- class VarWriteAccessCfgNode extends VarAccessCfgNode {
- override string getAPrimaryQlClass() { result = "VarWriteAccessCfgNode" }
+ class BinaryExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "BinaryExprCfgNode" }
- override VarWriteAccessChildMapping e;
+ override BinaryExprChildMapping e;
- override VarWriteAccess getExpr() { result = super.getExpr() }
+ override BinaryExpr getExpr() { result = e }
- predicate isExplicitWrite(StmtNodes::AssignStmtCfgNode assignment) {
- this = assignment.getLeftHandSide()
- }
+ ExprCfgNode getLeft() { e.hasCfgChild(e.getLeft(), this, result) }
- predicate isImplicitWrite() { e.isImplicit() }
+ ExprCfgNode getRight() { e.hasCfgChild(e.getRight(), this, result) }
}
- /** A control-flow node that wraps an argument expression. */
- class ArgumentCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ArgumentCfgNode" }
+ private class UnaryExprChildMapping extends ExprChildMapping, UnaryExpr {
+ override predicate relevantChild(Ast child) { child = this.getOperand() }
+ }
- override Argument e;
+ class UnaryExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "UnaryExprCfgNode" }
- final override Argument getExpr() { result = super.getExpr() }
+ override UnaryExprChildMapping e;
- /** Gets the position of this argument, if any. */
- int getPosition() { result = e.getPosition() }
+ override UnaryExpr getExpr() { result = e }
- /** Gets the name of this argument, if any. */
- string getName() { result = e.getName() }
+ ExprCfgNode getOperand() { e.hasCfgChild(e.getOperand(), this, result) }
+ }
- /** Holds if `this` is a qualifier to a call. */
- predicate isQualifier() { e.isQualifier() }
+ class ConstExprChildMapping extends ExprChildMapping, ConstExpr {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class ConstExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ConstExprCfgNode" }
+
+ override ConstExprChildMapping e;
- /** Gets the call for which this is an argument. */
- CallCfgNode getCall() { result.getAnArgument() = this or result.getQualifier() = this }
+ override ConstExpr getExpr() { result = e }
}
- private class InvokeMemberChildMapping extends ExprChildMapping, InvokeMemberExpr {
- override predicate relevantChild(Ast n) { n = this.getQualifier() or n = this.getAnArgument() }
+ class ConvertExprChildMapping extends ExprChildMapping, ConvertExpr {
+ override predicate relevantChild(Ast child) { child = this.getExpr() }
}
- /** A control-flow node that wraps an `InvokeMemberExpr` expression. */
- class InvokeMemberCfgNode extends ExprCfgNode, AbstractCallCfgNode {
- override string getAPrimaryQlClass() { result = "InvokeMemberCfgNode" }
+ class ConvertExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ConvertExprCfgNode" }
+
+ override ConvertExprChildMapping e;
- override InvokeMemberChildMapping e;
+ override ConvertExpr getExpr() { result = e }
- override InvokeMemberExpr getExpr() { result = super.getExpr() }
+ ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
+ }
- final override ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
+ class IndexExprChildMapping extends ExprChildMapping, IndexExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getBase()
+ or
+ child = this.getIndex()
+ }
+ }
- final override ExprCfgNode getArgument(int i) { e.hasCfgChild(e.getArgument(i), this, result) }
+ class IndexExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "IndexExprCfgNode" }
- final override ExprCfgNode getPositionalArgument(int i) { result = this.getArgument(i) }
+ override IndexExprChildMapping e;
- final override ExprCfgNode getNamedArgument(string name) { none() }
+ override IndexExpr getExpr() { result = e }
- final override ExprCfgNode getAnArgument() { e.hasCfgChild(e.getAnArgument(), this, result) }
+ ExprCfgNode getBase() { e.hasCfgChild(e.getBase(), this, result) }
- final override string getName() { result = e.getName() }
+ ExprCfgNode getIndex() { e.hasCfgChild(e.getIndex(), this, result) }
+ }
- final override ExprCfgNode getCommand() { none() }
+ private class IndexExprWriteAccessChildMapping extends IndexExprChildMapping, IndexExprWriteAccess
+ {
+ override predicate relevantChild(Ast child) {
+ super.relevantChild(child) or
+ this.isExplicitWrite(child)
+ }
}
- /** A control-flow node that wraps an `ConstructorCall` expression. */
- class ConstructorCallCfgNode extends InvokeMemberCfgNode {
- ConstructorCallCfgNode() { super.getExpr() instanceof ConstructorCall }
+ class IndexExprWriteAccessCfgNode extends IndexExprCfgNode {
+ override IndexExprWriteAccessChildMapping e;
+
+ override string getAPrimaryQlClass() { result = "IndexExprWriteAccessCfgNode" }
- final override ConstructorCall getExpr() { result = super.getExpr() }
+ override IndexExprWriteAccess getExpr() { result = e }
- Type getConstructedType() { result = this.getExpr().getConstructedType() }
+ final StmtNodes::AssignStmtCfgNode getAssignStmt() { this.isExplicitWrite(result) }
+
+ predicate isExplicitWrite(AstCfgNode assignmentCfg) {
+ exists(Ast assignment |
+ // this.isExplicitWrite(assignment) and
+ e.isExplicitWrite(assignment) and
+ e.hasCfgChild(assignment, this, assignmentCfg)
+ )
+ }
+
+ predicate isImplicitWrite() { e.isImplicitWrite() }
}
- /** A control-flow node that wraps a qualifier expression. */
- class QualifierCfgNode extends ExprCfgNode {
- QualifierCfgNode() { this = any(InvokeMemberCfgNode invoke).getQualifier() }
+ private class IndexExprReadAccessChildMapping extends IndexExprChildMapping, IndexExprReadAccess {
+ override predicate relevantChild(Ast child) { super.relevantChild(child) }
+ }
+
+ class IndexExprReadAccessCfgNode extends IndexExprCfgNode {
+ override IndexExprReadAccessChildMapping e;
- InvokeMemberCfgNode getInvokeMember() { this = result.getQualifier() }
+ override string getAPrimaryQlClass() { result = "IndexExprAccessCfgNode" }
+
+ override IndexExprReadAccess getExpr() { result = e }
}
- class TypeNameChildMapping extends ExprChildMapping, TypeNameExpr {
- override predicate relevantChild(Ast n) { none() }
+ class CallExprChildMapping extends ExprChildMapping, CallExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getQualifier()
+ or
+ child = this.getAnArgument()
+ or
+ child = this.getCallee()
+ }
}
- /** A control-flow node that wraps a `TypeName` expression. */
- class TypeNameCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "TypeNameCfgNode" }
+ class CallExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "CallExprCfgNode" }
+
+ override CallExprChildMapping e;
+
+ override CallExpr getExpr() { result = e }
- override TypeNameChildMapping e;
+ ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
- override TypeNameExpr getExpr() { result = super.getExpr() }
+ ExprCfgNode getArgument(int i) { e.hasCfgChild(e.getArgument(i), this, result) }
+
+ ExprCfgNode getAnArgument() { result = this.getArgument(_) }
+
+ /** Gets the name that is used to select the callee. */
+ string getName() { result = e.getName() }
+
+ predicate hasName(string name) { this.getName() = name }
+
+ /** Gets the i'th positional argument to this call. */
+ ExprCfgNode getPositionalArgument(int i) {
+ e.hasCfgChild(e.getPositionalArgument(i), this, result)
+ }
+
+ /** Holds if an argument with name `name` is provided to this call. */
+ final predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
+
+ /** Gets the argument to this call with the name `name`. */
+ ExprCfgNode getNamedArgument(string name) {
+ e.hasCfgChild(e.getNamedArgument(name), this, result)
+ }
- Type getType() { result = this.getExpr().getType() }
+ ExprCfgNode getCallee() { e.hasCfgChild(e.getCallee(), this, result) }
- string getTypeName() { result = this.getExpr().getName() }
+ predicate isStatic() { this.getExpr().isStatic() }
}
- class ConditionalChildMapping extends ExprChildMapping, ConditionalExpr {
- override predicate relevantChild(Ast n) { n = this.getCondition() or n = this.getABranch() }
+ class ObjectCreationChildMapping extends CallExprChildMapping instanceof ObjectCreation {
+ override predicate relevantChild(Ast child) { child = super.getConstructedTypeExpr() }
}
- /** A control-flow node that wraps a `ConditionalExpr` expression. */
- class ConditionalCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ConditionalCfgNode" }
+ class ObjectCreationCfgNode extends CallExprCfgNode {
+ // TODO: Also calls to Activator.CreateInstance
+ override string getAPrimaryQlClass() { result = "CallExprCfgNode" }
- override ConditionalChildMapping e;
+ override ObjectCreationChildMapping e;
- final override ConditionalExpr getExpr() { result = super.getExpr() }
+ override ObjectCreation getExpr() { result = e }
- final ExprCfgNode getCondition() { e.hasCfgChild(e.getCondition(), this, result) }
+ string getConstructedTypeName() { result = this.getExpr().getConstructedTypeName() }
- final ExprCfgNode getBranch(boolean value) { e.hasCfgChild(e.getBranch(value), this, result) }
+ ExprCfgNode getConstructedTypeExpr() {
+ e.hasCfgChild(this.getExpr().getConstructedTypeExpr(), this, result)
+ }
+ }
+
+ class CallOperatorChildMapping extends CallExprChildMapping instanceof CallOperator {
+ override predicate relevantChild(Ast child) { none() }
+ }
- final ExprCfgNode getABranch() { result = this.getBranch(_) }
+ class CallOperatorCfgNode extends CallExprCfgNode {
+ override string getAPrimaryQlClass() { result = "CallOperatorCfgNode" }
- final ExprCfgNode getIfTrue() { e.hasCfgChild(e.getIfTrue(), this, result) }
+ override CallOperatorChildMapping e;
- final ExprCfgNode getIfFalse() { e.hasCfgChild(e.getIfFalse(), this, result) }
+ override CallOperator getExpr() { result = e }
+
+ ExprCfgNode getCommand() { result = this.getArgument(0) }
}
- class MemberChildMapping extends ExprChildMapping, MemberExpr {
- override predicate relevantChild(Ast n) { n = this.getQualifier() or n = this.getMember() }
+ class MemberExprChildMapping extends ExprChildMapping, MemberExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getQualifier()
+ or
+ child = this.getMemberExpr()
+ }
}
- /** A control-flow node that wraps a `MemberExpr` expression. */
- class MemberCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "MemberCfgNode" }
+ class MemberExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "MemberExprCfgNode" }
+
+ override MemberExprChildMapping e;
- override MemberChildMapping e;
+ override MemberExpr getExpr() { result = e }
- final override MemberExpr getExpr() { result = super.getExpr() }
+ ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
- final ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
+ ExprCfgNode getMemberExpr() { e.hasCfgChild(e.getMemberExpr(), this, result) }
- final string getMemberName() { result = e.getMemberName() }
+ string getMemberName() { result = e.getMemberName() }
predicate isStatic() { e.isStatic() }
}
- /** A control-flow node that wraps a `MemberExpr` expression that is being written to. */
- class MemberCfgWriteAccessNode extends MemberCfgNode {
- MemberCfgWriteAccessNode() { this.getExpr() instanceof MemberExprWriteAccess }
+ private class MemberExprWriteAccessChildMapping extends MemberExprChildMapping,
+ MemberExprWriteAccess
+ {
+ override predicate relevantChild(Ast child) {
+ super.relevantChild(child) or
+ this.isExplicitWrite(child)
+ }
+ }
+
+ class MemberExprWriteAccessCfgNode extends MemberExprCfgNode {
+ override MemberExprWriteAccessChildMapping e;
+
+ override string getAPrimaryQlClass() { result = "MemberExprWriteAccessCfgNode" }
- StmtNodes::AssignStmtCfgNode getAssignStmt() { result.getLeftHandSide() = this }
+ override MemberExprWriteAccess getExpr() { result = e }
+
+ final StmtNodes::AssignStmtCfgNode getAssignStmt() { this.isExplicitWrite(result) }
+
+ predicate isExplicitWrite(AstCfgNode assignmentCfg) {
+ exists(Ast assignment |
+ // this.isExplicitWrite(assignment) and
+ e.isExplicitWrite(assignment) and
+ e.hasCfgChild(assignment, this, assignmentCfg)
+ )
+ }
+
+ predicate isImplicitWrite() { e.isImplicitWrite() }
}
- /** A control-flow node that wraps a `MemberExpr` expression that is being read from. */
- class MemberCfgReadAccessNode extends MemberCfgNode {
- MemberCfgReadAccessNode() { this.getExpr() instanceof MemberExprReadAccess }
+ private class MemberExprReadAccessChildMapping extends MemberExprChildMapping,
+ MemberExprReadAccess
+ {
+ override predicate relevantChild(Ast child) { super.relevantChild(child) }
}
- class ArrayLiteralChildMapping extends ExprChildMapping, ArrayLiteral {
- override predicate relevantChild(Ast n) { n = this.getAnElement() }
+ class MemberExprReadAccessCfgNode extends MemberExprCfgNode {
+ override MemberExprReadAccessChildMapping e;
+
+ override string getAPrimaryQlClass() { result = "MemberExprReadAccessCfgNode" }
+
+ override MemberExprReadAccess getExpr() { result = e }
}
- class ArrayLiteralCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ArrayLiteralCfgNode" }
+ class TypeNameExprChildMapping extends ExprChildMapping, TypeNameExpr {
+ override predicate relevantChild(Ast child) { none() }
+ }
- override ArrayLiteralChildMapping e;
+ class TypeNameExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "TypeExprCfgNode" }
+
+ override TypeNameExprChildMapping e;
+
+ override TypeNameExpr getExpr() { result = e }
+
+ string getName() { result = e.getName() }
+
+ string getNamespace() { result = e.getNamespace() }
- ExprCfgNode getElement(int i) { e.hasCfgChild(e.getElement(i), this, result) }
+ string getPossiblyQualifiedName() { result = e.getPossiblyQualifiedName() }
- ExprCfgNode getAnElement() { e.hasCfgChild(e.getAnElement(), this, result) }
+ predicate isQualified() { e.isQualified() }
}
- class IndexChildMapping extends ExprChildMapping, IndexExpr {
- override predicate relevantChild(Ast n) { n = this.getBase() or n = this.getIndex() }
+ class QualifiedTypeNameExprCfgNode extends TypeNameExprCfgNode {
+ QualifiedTypeNameExprCfgNode() { e.isQualified() }
+
+ override string getAPrimaryQlClass() { result = "QualifiedTypeNameExprCfgNode" }
+
+ override QualifiedTypeNameExpr getExpr() { result = e }
}
- /** A control-flow node that wraps a `MemberExpr` expression. */
- class IndexCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "IndexCfgNode" }
+ class ErrorExprChildMapping extends ExprChildMapping, ErrorExpr {
+ override predicate relevantChild(Ast child) { none() }
+ }
- override IndexChildMapping e;
+ class ErrorExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ErrorExprCfgNode" }
- final ExprCfgNode getBase() { e.hasCfgChild(e.getBase(), this, result) }
+ override ErrorExprChildMapping e;
- final ExprCfgNode getIndex() { e.hasCfgChild(e.getIndex(), this, result) }
+ override ErrorExpr getExpr() { result = e }
}
- /** A control-flow node that wraps a `MemberExpr` expression that is being written to. */
- class IndexCfgWriteNode extends IndexCfgNode {
- IndexCfgWriteNode() { this.getExpr() instanceof IndexExprWrite }
+ class ScriptBlockExprChildMapping extends ExprChildMapping, ScriptBlockExpr {
+ override predicate relevantChild(Ast child) { child = this.getBody() }
+ }
+
+ class ScriptBlockExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ScriptBlockExprCfgNode" }
+
+ override ScriptBlockExprChildMapping e;
+
+ override ScriptBlockExpr getExpr() { result = e }
- StmtNodes::AssignStmtCfgNode getAssignStmt() { result.getLeftHandSide() = this }
+ ScriptBlockCfgNode getBody() { e.hasCfgChild(e.getBody(), this, result) }
}
- /** A control-flow node that wraps a `MemberExpr` expression that is being read from. */
- class IndexCfgReadNode extends IndexCfgNode {
- IndexCfgReadNode() { this.getExpr() instanceof IndexExprRead }
+ class StringLiteralExprChildMapping extends ExprChildMapping, StringConstExpr {
+ override predicate relevantChild(Ast child) { none() }
}
- class ArrayExprChildMapping extends ExprChildMapping, ArrayExpr {
- override predicate relevantChild(Ast n) { n = this.getStmtBlock() or n = this.getAnElement() }
+ class StringLiteralExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "StringLiteralExprCfgNode" }
+
+ override StringLiteralExprChildMapping e;
+
+ override StringConstExpr getExpr() { result = e }
+
+ string getValueString() { result = e.getValueString() }
}
- class ArrayExprCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ArrayExprCfgNode" }
+ class ExpandableStringExprChildMapping extends ExprChildMapping, ExpandableStringExpr {
+ override predicate relevantChild(Ast child) { child = this.getAnExpr() }
+ }
- override ArrayExprChildMapping e;
+ class ExpandableStringExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ExpandableStringExprCfgNode" }
- ExprCfgNode getElement(int i) { e.hasCfgChild(e.getElement(i), this, result) }
+ override ExpandableStringExprChildMapping e;
- ExprCfgNode getAnElement() { result = this.getElement(_) }
+ override ExpandableStringExpr getExpr() { result = e }
+
+ ExprCfgNode getExpr(int i) { e.hasCfgChild(e.getExpr(i), this, result) }
- StmtBlockCfgNode getStmtBlock() { e.hasCfgChild(e.getStmtBlock(), this, result) }
+ ExprCfgNode getAnExpr() { result = this.getExpr(_) }
}
- class HashTableChildMapping extends ExprChildMapping, HashTableExpr {
- override predicate relevantChild(Ast n) { this.hasEntry(_, _, n) or this.hasEntry(_, n, _) }
+ class VarAccessCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "VarAccessExprCfgNode" }
+
+ override VarAccess e;
+
+ override VarAccess getExpr() { result = e }
+
+ Variable getVariable() { result = e.getVariable() }
+ }
+
+ private class VarWriteAccessChildMapping extends ExprChildMapping, VarWriteAccess {
+ override predicate relevantChild(Ast child) { this.isExplicitWrite(child) }
}
- class HashTableCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "HashMapCfgNode" }
+ class VarWriteAccessCfgNode extends VarAccessCfgNode {
+ override VarWriteAccessChildMapping e;
+
+ override string getAPrimaryQlClass() { result = "VarWriteAccessCfgNode" }
- override HashTableChildMapping e;
+ override VarWriteAccess getExpr() { result = e }
- override HashTableExpr getExpr() { result = super.getExpr() }
+ final StmtNodes::AssignStmtCfgNode getAssignStmt() { this.isExplicitWrite(result) }
- StmtCfgNode getElement(ExprCfgNode key) {
- exists(Expr eKey |
- eKey = key.getAstNode() and
- e.hasCfgChild(eKey, this, key) and
- e.hasCfgChild(e.getElement(eKey), this, result)
+ predicate isExplicitWrite(AstCfgNode assignmentCfg) {
+ exists(Ast assignment |
+ e.isExplicitWrite(assignment) and
+ e.hasCfgChild(assignment, this, assignmentCfg)
)
}
- predicate hasKey(ExprCfgNode key) { exists(this.getElement(key)) }
+ predicate isImplicitWrite() { e.isImplicitWrite() }
+ }
+
+ class VarReadAccessCfgNode extends VarAccessCfgNode {
+ override VarReadAccess e;
+
+ override string getAPrimaryQlClass() { result = "VarReadAccessCfgNode" }
+
+ override VarReadAccess getExpr() { result = e }
+ }
+
+ class HashTableExprChildMapping extends ExprChildMapping, HashTableExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getAKey()
+ or
+ child = this.getAValue()
+ }
+ }
+
+ class HashTableExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "HashTableExprCfgNode" }
+
+ override HashTableExprChildMapping e;
- StmtCfgNode getAnElement() { result = this.getElement(_) }
+ override HashTableExpr getExpr() { result = e }
- predicate hasEntry(int index, ExprCfgNode key, StmtCfgNode value) {
- exists(Expr eKey, Stmt sValue |
- e.hasCfgChild(eKey, this, key) and
- e.hasCfgChild(sValue, this, value) and
- e.hasEntry(index, eKey, sValue)
+ ExprCfgNode getKey(int i) { e.hasCfgChild(e.getKey(i), this, result) }
+
+ ExprCfgNode getAnKey() { result = this.getKey(_) }
+
+ ExprCfgNode getValue(int i) { e.hasCfgChild(e.getKey(i), this, result) }
+
+ ExprCfgNode getValueFromKey(ExprCfgNode key) {
+ exists(int i |
+ this.getKey(i) = key and
+ result = this.getValue(i)
)
}
+
+ ExprCfgNode getAValue() { result = this.getValue(_) }
}
- class ConvertExprChildMapping extends ExprChildMapping, ConvertExpr {
- override predicate relevantChild(Ast n) { n = this.getBase() }
+ class PipelineChildMapping extends ExprChildMapping, Pipeline {
+ override predicate relevantChild(Ast child) { child = this.getAComponent() }
}
- class ConvertCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ConvertCfgNode" }
+ class PipelineCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "PipelineCfgNode" }
- override ConvertExprChildMapping e;
+ override PipelineChildMapping e;
- override ConvertExpr getExpr() { result = e }
+ override Pipeline getExpr() { result = e }
- final ExprCfgNode getBase() { e.hasCfgChild(e.getBase(), this, result) }
+ ExprCfgNode getComponent(int i) { e.hasCfgChild(e.getComponent(i), this, result) }
- TypeConstraint getType() { result = e.getType() }
+ ExprCfgNode getAComponent() { result = this.getComponent(_) }
}
- class ParenExprChildMapping extends ExprChildMapping, ParenExpr {
- override predicate relevantChild(Ast n) { n = this.getBase() }
+ class PipelineChainChildMapping extends ExprChildMapping, PipelineChain {
+ override predicate relevantChild(Ast child) {
+ child = this.getLeft() or child = this.getRight()
+ }
}
- class ParenCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ParenExprCfgNode" }
+ class PipelineChainCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "PipelineChainCfgNode" }
- override ParenExprChildMapping e;
+ override PipelineChainChildMapping e;
- override ParenExpr getExpr() { result = e }
+ override PipelineChain getExpr() { result = e }
- final StmtCfgNode getBase() { e.hasCfgChild(e.getBase(), this, result) }
+ ExprCfgNode getLeft() { e.hasCfgChild(e.getLeft(), this, result) }
+
+ ExprCfgNode getRight() { e.hasCfgChild(e.getRight(), this, result) }
}
- class UnaryExprChildMapping extends ExprChildMapping, UnaryExpr {
- override predicate relevantChild(Ast n) { n = this.getOperand() }
+ class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getCondition()
+ or
+ child = this.getIfTrue()
+ or
+ child = this.getIfFalse()
+ }
}
- class UnaryCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "UnaryExprCfgNode" }
+ class ConditionalExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ConditionalExprCfgNode" }
- override UnaryExprChildMapping e;
+ override ConditionalExprChildMapping e;
- override UnaryExpr getExpr() { result = e }
+ override ConditionalExpr getExpr() { result = e }
+
+ ExprCfgNode getCondition() { e.hasCfgChild(e.getCondition(), this, result) }
+
+ ExprCfgNode getIfTrue() { e.hasCfgChild(e.getIfTrue(), this, result) }
- final ExprCfgNode getOperand() { e.hasCfgChild(e.getOperand(), this, result) }
+ ExprCfgNode getIfFalse() { e.hasCfgChild(e.getIfFalse(), this, result) }
+
+ ExprCfgNode getBranch(boolean b) {
+ b = true and
+ result = this.getIfTrue()
+ or
+ b = false and
+ result = this.getIfFalse()
+ }
+
+ ExprCfgNode getABranch() { result = this.getBranch(_) }
}
- class BinaryExprChildMapping extends ExprChildMapping, BinaryExpr {
- override predicate relevantChild(Ast n) { n = this.getLeft() or n = this.getRight() }
+ class ExpandableSubExprChildMapping extends ExprChildMapping, ExpandableSubExpr {
+ override predicate relevantChild(Ast child) { child = this.getExpr() }
}
- class BinaryCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "BinaryExprCfgNode" }
+ class ExpandableSubExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "ExpandableSubExprCfgNode" }
- override BinaryExprChildMapping e;
+ override ExpandableSubExprChildMapping e;
- override BinaryExpr getExpr() { result = e }
+ override ExpandableSubExpr getExpr() { result = e }
+
+ ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
+ }
+
+ class UsingExprChildMapping extends ExprChildMapping, UsingExpr {
+ override predicate relevantChild(Ast child) { child = this.getExpr() }
+ }
+
+ class UsingExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "UsingExprCfgNode" }
+
+ override UsingExprChildMapping e;
+
+ override UsingExpr getExpr() { result = e }
+
+ ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
+ }
+
+ class AttributedExprChildMapping extends ExprChildMapping, AttributedExpr {
+ override predicate relevantChild(Ast child) {
+ child = this.getExpr() or
+ child = this.getAttribute()
+ }
+ }
+
+ class AttributedExprCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "TAttributedExprCfgNode" }
+
+ override AttributedExprChildMapping e;
+
+ override AttributedExpr getExpr() { result = e }
+
+ ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
+
+ ExprCfgNode getAttribute() { e.hasCfgChild(e.getAttribute(), this, result) }
+ }
+
+ class IfChildMapping extends ExprChildMapping, If {
+ override predicate relevantChild(Ast child) {
+ child = this.getACondition()
+ or
+ child = this.getAThen()
+ or
+ child = this.getElse()
+ }
+ }
+
+ class IfCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "IfCfgNode" }
+
+ override IfChildMapping e;
+
+ override If getExpr() { result = e }
+
+ ExprCfgNode getCondition(int i) { e.hasCfgChild(e.getCondition(i), this, result) }
+
+ ExprCfgNode getACondition() { result = this.getCondition(_) }
+
+ StmtCfgNode getThen(int i) { e.hasCfgChild(e.getThen(i), this, result) }
+
+ StmtCfgNode getAThen() { result = this.getThen(_) }
+
+ StmtCfgNode getElse() { e.hasCfgChild(e.getElse(), this, result) }
+ }
+
+ class LiteralChildMapping extends ExprChildMapping, Literal {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class LiteralCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "LiteralCfgNode" }
+
+ override LiteralChildMapping e;
+
+ override Literal getExpr() { result = e }
+ }
+
+ class BoolLiteralChildMapping extends ExprChildMapping, BoolLiteral {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class BoolLiteralCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "BoolLiteralCfgNode" }
+
+ override BoolLiteralChildMapping e;
+
+ override BoolLiteral getExpr() { result = e }
+ }
+
+ class NullLiteralChildMapping extends ExprChildMapping, NullLiteral {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class NullLiteralCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "NullLiteralCfgNode" }
- final ExprCfgNode getLeft() { e.hasCfgChild(e.getLeft(), this, result) }
+ override NullLiteralChildMapping e;
- final ExprCfgNode getRight() { e.hasCfgChild(e.getRight(), this, result) }
+ override NullLiteral getExpr() { result = e }
}
- class OperationChildMapping extends ExprChildMapping instanceof Operation {
- override predicate relevantChild(Ast n) { n = super.getAnOperand() }
+ class ArgumentCfgNode extends ExprCfgNode {
+ override Argument e;
+
+ CallExprCfgNode getCall() { result.getAnArgument() = this }
+
+ string getName() { result = e.getName() }
+
+ int getPosition() { result = e.getPosition() }
+ }
+
+ class QualifierCfgNode extends ExprCfgNode {
+ override Qualifier e;
+
+ CallExprCfgNode getCall() { result.getQualifier() = this }
+ }
+
+ private class EnvVariableChildMapping extends ExprChildMapping, EnvVariable {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class EnvVariableCfgNode extends ExprCfgNode {
+ override string getAPrimaryQlClass() { result = "EnvVariableCfgNode" }
+
+ override EnvVariableChildMapping e;
+
+ override EnvVariable getExpr() { result = e }
+
+ string getName() { result = e.getName() }
+ }
+
+ private class OperationChildMapping extends ExprChildMapping, Operation {
+ override predicate relevantChild(Ast child) { child = this.getAnOperand() }
}
class OperationCfgNode extends ExprCfgNode {
@@ -563,166 +979,421 @@ module ExprNodes {
override Operation getExpr() { result = e }
- final ExprCfgNode getAnOperand() { e.hasCfgChild(this.getExpr().getAnOperand(), this, result) }
+ ExprCfgNode getAnOperand() { e.hasCfgChild(e.getAnOperand(), this, result) }
+ }
+}
+
+module StmtNodes {
+ private class AssignStmtChildMapping extends NonExprChildMapping, AssignStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getLeftHandSide()
+ or
+ child = this.getRightHandSide()
+ }
}
- class ExpandableStringChildMappinig extends ExprChildMapping, ExpandableStringExpr {
- override predicate relevantChild(Ast n) { n = this.getAnExpr() }
+ class AssignStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "AssignStmtCfgNode" }
+
+ override AssignStmtChildMapping s;
+
+ override AssignStmt getStmt() { result = s }
+
+ ExprCfgNode getLeftHandSide() { s.hasCfgChild(s.getLeftHandSide(), this, result) }
+
+ ExprCfgNode getRightHandSide() { s.hasCfgChild(s.getRightHandSide(), this, result) }
}
- class ExpandableStringCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "ExpandableStringCfgNode" }
+ class BreakStmtChildMapping extends NonExprChildMapping, BreakStmt {
+ override predicate relevantChild(Ast child) { none() }
+ }
- override ExpandableStringChildMappinig e;
+ class BreakStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "BreakStmtCfgNode" }
- override ExpandableStringExpr getExpr() { result = e }
+ override BreakStmtChildMapping s;
- ExprCfgNode getExpr(int i) { e.hasCfgChild(e.getExpr(i), this, result) }
+ override BreakStmt getStmt() { result = s }
+ }
- ExprCfgNode getAnExpr() { result = this.getExpr(_) }
+ class ContinueStmtChildMapping extends NonExprChildMapping, ContinueStmt {
+ override predicate relevantChild(Ast child) { none() }
}
-}
-module StmtNodes {
- private class CmdChildMapping extends CmdBaseChildMapping, Cmd {
- override predicate relevantChild(Ast n) { n = this.getAnArgument() or n = this.getCommand() }
+ class ContinueStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ContinueStmtCfgNode" }
+
+ override ContinueStmtChildMapping s;
+
+ override ContinueStmt getStmt() { result = s }
+ }
+
+ class DataStmtChildMapping extends NonExprChildMapping, DataStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getACmdAllowed() or child = this.getBody()
+ }
+ }
+
+ class DataStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "DataStmtCfgNode" }
+
+ override DataStmtChildMapping s;
+
+ override DataStmt getStmt() { result = s }
+
+ ExprCfgNode getCmdAllowed(int i) { s.hasCfgChild(s.getCmdAllowed(i), this, result) }
+
+ ExprCfgNode getACmdAllowed() { result = this.getCmdAllowed(_) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
}
- /** A control-flow node that wraps a `Cmd` AST expression. */
- class CmdCfgNode extends CmdBaseCfgNode, AbstractCallCfgNode {
- override string getAPrimaryQlClass() { result = "CmdCfgNode" }
+ class DoUntilStmtChildMapping extends NonExprChildMapping, DoUntilStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getCondition() or child = this.getBody()
+ }
+ }
- override CmdChildMapping s;
+ class DoUntilStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "DoUntilStmtCfgNode" }
- override Cmd getStmt() { result = super.getStmt() }
+ override DoUntilStmtChildMapping s;
- override ExprCfgNode getArgument(int i) { s.hasCfgChild(s.getArgument(i), this, result) }
+ override DoUntilStmt getStmt() { result = s }
- override ExprCfgNode getPositionalArgument(int i) {
- s.hasCfgChild(s.getPositionalArgument(i), this, result)
+ ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+ }
+
+ class DoWhileStmtChildMapping extends NonExprChildMapping, DoWhileStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getCondition() or child = this.getBody()
}
+ }
+
+ class DoWhileStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "DoWhileStmtCfgNode" }
+
+ override DoWhileStmtChildMapping s;
+
+ override DoWhileStmt getStmt() { result = s }
+
+ ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+ }
+
+ class ErrorStmtChildMapping extends NonExprChildMapping, ErrorStmt {
+ override predicate relevantChild(Ast child) { none() }
+ }
- override ExprCfgNode getNamedArgument(string name) {
- s.hasCfgChild(s.getNamedArgument(name), this, result)
+ class ErrorStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ErrorStmtCfgNode" }
+
+ override ErrorStmtChildMapping s;
+
+ override ErrorStmt getStmt() { result = s }
+ }
+
+ class ExitStmtChildMapping extends NonExprChildMapping, ExitStmt {
+ override predicate relevantChild(Ast child) { child = this.getPipeline() }
+ }
+
+ class ExitStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ExitStmtCfgNode" }
+
+ override ExitStmtChildMapping s;
+
+ override ExitStmt getStmt() { result = s }
+
+ ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
+ }
+
+ class DynamicStmtChildMapping extends NonExprChildMapping, DynamicStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getName() or child = this.getScriptBlock() or child = this.getHashTableExpr()
}
+ }
+
+ class DynamicStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "DynamicStmtCfgNode" }
- override ExprCfgNode getAnArgument() { s.hasCfgChild(s.getAnArgument(), this, result) }
+ override DynamicStmtChildMapping s;
- final override ExprCfgNode getCommand() { s.hasCfgChild(s.getCommand(), this, result) }
+ override DynamicStmt getStmt() { result = s }
- final override string getName() { result = s.getCommandName() }
+ ExprCfgNode getName() { s.hasCfgChild(s.getName(), this, result) }
- /** Holds if the command is qualified. */
- predicate isQualified() { s.isQualified() }
+ ExprCfgNode getScriptBlock() { s.hasCfgChild(s.getScriptBlock(), this, result) }
- /** Gets the namespace qualifier of this command, if any. */
- string getNamespaceQualifier() { result = s.getNamespaceQualifier() }
+ ExprCfgNode getHashTableExpr() { s.hasCfgChild(s.getHashTableExpr(), this, result) }
}
- /** A control-flow node that wraps a call to operator `&` */
- class CallOperatorCfgNode extends CmdCfgNode {
- CallOperatorCfgNode() { this.getStmt() instanceof CallOperator }
+ class ForEachStmtChildMapping extends NonExprChildMapping, ForEachStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getVarAccess() or child = this.getIterableExpr() or child = this.getBody()
+ }
+ }
+
+ class ForEachStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ForEachStmtCfgNode" }
+
+ override ForEachStmtChildMapping s;
+
+ override ForEachStmt getStmt() { result = s }
+
+ ExprCfgNode getVarAccess() { s.hasCfgChild(s.getVarAccess(), this, result) }
+
+ ExprCfgNode getIterableExpr() { s.hasCfgChild(s.getIterableExpr(), this, result) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
}
- private class AssignStmtChildMapping extends PipelineBaseChildMapping, AssignStmt {
- override predicate relevantChild(Ast n) {
- n = this.getLeftHandSide() or n = this.getRightHandSide()
+ class ForStmtChildMapping extends NonExprChildMapping, ForStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getInitializer() or
+ child = this.getCondition() or
+ child = this.getIterator() or
+ child = this.getBody()
}
}
- /** A control-flow node that wraps an `AssignStmt` AST expression. */
- class AssignStmtCfgNode extends PipelineBaseCfgNode {
- override string getAPrimaryQlClass() { result = "AssignCfgNode" }
+ class ForStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ForStmtCfgNode" }
- override AssignStmtChildMapping s;
+ override ForStmtChildMapping s;
+
+ override ForStmt getStmt() { result = s }
+
+ AstCfgNode getInitializer() { s.hasCfgChild(s.getInitializer(), this, result) }
- override AssignStmt getStmt() { result = super.getStmt() }
+ ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
- /** Gets the LHS of this assignment. */
- final ExprCfgNode getLeftHandSide() { s.hasCfgChild(s.getLeftHandSide(), this, result) }
+ AstCfgNode getIterator() { s.hasCfgChild(s.getIterator(), this, result) }
- /** Gets the RHS of this assignment. */
- final StmtCfgNode getRightHandSide() { s.hasCfgChild(s.getRightHandSide(), this, result) }
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
}
- class CmdExprChildMapping extends CmdBaseChildMapping, CmdExpr {
- override predicate relevantChild(Ast n) { n = this.getExpr() }
+ class GotoStmtChildMapping extends NonExprChildMapping, GotoStmt {
+ override predicate relevantChild(Ast child) { child = this.getLabel() }
}
- /** A control-flow node that wraps a `CmdExpr` expression. */
- class CmdExprCfgNode extends CmdBaseCfgNode {
- override string getAPrimaryQlClass() { result = "CmdExprCfgNode" }
+ class GotoStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "GotoStmtCfgNode" }
- override CmdExprChildMapping s;
+ override GotoStmtChildMapping s;
- override CmdExpr getStmt() { result = super.getStmt() }
+ override GotoStmt getStmt() { result = s }
- final ExprCfgNode getExpr() { s.hasCfgChild(s.getExpr(), this, result) }
+ ExprCfgNode getLabel() { s.hasCfgChild(s.getLabel(), this, result) }
}
- class PipelineBaseChildMapping extends NonExprChildMapping, PipelineBase {
- override predicate relevantChild(Ast n) { none() }
+ class ReturnStmtChildMapping extends NonExprChildMapping, ReturnStmt {
+ override predicate relevantChild(Ast child) { child = this.getPipeline() }
}
- class PipelineBaseCfgNode extends StmtCfgNode {
- override string getAPrimaryQlClass() { result = "PipelineBaseCfgNode" }
+ class ReturnStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ReturnStmtCfgNode" }
- override PipelineBaseChildMapping s;
+ override ReturnStmtChildMapping s;
- override PipelineBase getStmt() { result = super.getStmt() }
+ override ReturnStmt getStmt() { result = s }
+
+ ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
}
- class ChainableChildMapping extends PipelineBaseChildMapping, Chainable {
- override predicate relevantChild(Ast n) { none() }
+ class StmtBlockChildMapping extends NonExprChildMapping, StmtBlock {
+ override predicate relevantChild(Ast child) { child = this.getAStmt() }
}
- class ChainableCfgNode extends PipelineBaseCfgNode {
- override string getAPrimaryQlClass() { result = "ChainableCfgNode" }
+ class StmtBlockCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "StmtBlockCfgNode" }
+
+ override StmtBlockChildMapping s;
+
+ override StmtBlock getStmt() { result = s }
- override ChainableChildMapping s;
+ StmtCfgNode getStmt(int i) { s.hasCfgChild(s.getStmt(i), this, result) }
- override Chainable getStmt() { result = super.getStmt() }
+ StmtCfgNode getAStmt() { result = this.getStmt(_) }
}
- class PipelineChainChildMapping extends ChainableChildMapping, PipelineChain {
- override predicate relevantChild(Ast n) { n = this.getLeft() or n = this.getRight() }
+ class SwitchStmtChildMapping extends NonExprChildMapping, SwitchStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getCondition() or
+ child = this.getDefault() or
+ child = this.getACase() or
+ child = this.getAPattern()
+ }
}
- class PipelineChainCfgNode extends ChainableCfgNode {
- override string getAPrimaryQlClass() { result = "PipelineChainCfgNode" }
+ class SwitchStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "SwitchStmtCfgNode" }
+
+ override SwitchStmtChildMapping s;
+
+ override SwitchStmt getStmt() { result = s }
- override PipelineChainChildMapping s;
+ ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
- override PipelineChain getStmt() { result = super.getStmt() }
+ StmtCfgNode getDefault() { s.hasCfgChild(s.getDefault(), this, result) }
- final ChainableCfgNode getLeft() { s.hasCfgChild(s.getLeft(), this, result) }
+ StmtCfgNode getCase(int i) { s.hasCfgChild(s.getCase(i), this, result) }
- final ChainableCfgNode getRight() { s.hasCfgChild(s.getRight(), this, result) }
+ StmtCfgNode getACase() { result = this.getCase(_) }
+
+ ExprCfgNode getPattern(int i) { s.hasCfgChild(s.getPattern(i), this, result) }
+
+ ExprCfgNode getAPattern() { result = this.getPattern(_) }
}
- class CmdBaseChildMapping extends ChainableChildMapping, CmdBase { }
+ class ThrowStmtChildMapping extends NonExprChildMapping, ThrowStmt {
+ override predicate relevantChild(Ast child) { child = this.getPipeline() }
+ }
- class CmdBaseCfgNode extends ChainableCfgNode {
- override string getAPrimaryQlClass() { result = "CmdBaseCfgNode" }
+ class ThrowStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ThrowStmtCfgNode" }
- override CmdBaseChildMapping s;
+ override ThrowStmtChildMapping s;
- override CmdBase getStmt() { result = super.getStmt() }
+ override ThrowStmt getStmt() { result = s }
+
+ ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
}
- class PipelineChildMapping extends ChainableChildMapping, Pipeline {
- override predicate relevantChild(Ast n) { n = this.getAComponent() }
+ class TrapStmtChildMapping extends NonExprChildMapping, TrapStmt {
+ override predicate relevantChild(Ast child) { child = this.getBody() }
}
- class PipelineCfgNode extends ChainableCfgNode {
- override string getAPrimaryQlClass() { result = "PipelineCfgNode" }
+ class TrapStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "TrapStmtCfgNode" }
+
+ override TrapStmtChildMapping s;
+
+ override TrapStmt getStmt() { result = s }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+ }
+
+ class TryStmtChildMapping extends NonExprChildMapping, TryStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getBody() or
+ child = this.getFinally() or
+ child = this.getACatchClause()
+ }
+ }
+
+ class TryStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "TryStmtCfgNode" }
+
+ override TryStmtChildMapping s;
+
+ override TryStmt getStmt() { result = s }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+
+ StmtCfgNode getFinally() { s.hasCfgChild(s.getFinally(), this, result) }
+
+ StmtCfgNode getCatchClause(int i) { s.hasCfgChild(s.getCatchClause(i), this, result) }
+ }
+
+ class UsingStmtChildMapping extends NonExprChildMapping, UsingStmt {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class UsingStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "UsingStmtCfgNode" }
+
+ override UsingStmtChildMapping s;
+
+ override UsingStmt getStmt() { result = s }
+ }
+
+ class WhileStmtChildMapping extends NonExprChildMapping, WhileStmt {
+ override predicate relevantChild(Ast child) {
+ child = this.getCondition() or
+ child = this.getBody()
+ }
+ }
+
+ class WhileStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "WhileStmtCfgNode" }
+
+ override WhileStmtChildMapping s;
+
+ override WhileStmt getStmt() { result = s }
+
+ ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+ }
+
+ class ConfigurationChildMapping extends NonExprChildMapping, Configuration {
+ override predicate relevantChild(Ast child) { child = this.getName() or child = this.getBody() }
+ }
+
+ class ConfigurationCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ConfigurationCfgNode" }
+
+ override ConfigurationChildMapping s;
+
+ override Configuration getStmt() { result = s }
+
+ ExprCfgNode getName() { s.hasCfgChild(s.getName(), this, result) }
+
+ StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
+ }
+
+ class TypeStmtChildMapping extends NonExprChildMapping, TypeDefinitionStmt {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class TypeDefinitionStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "TypeStmtCfgNode" }
+
+ override TypeStmtChildMapping s;
+
+ override TypeDefinitionStmt getStmt() { result = s }
+
+ Member getMember(int i) { result = s.getMember(i) }
+
+ Member getAMember() { result = this.getMember(_) }
+
+ TypeConstraint getBaseType(int i) { result = s.getBaseType(i) }
+
+ TypeConstraint getABaseType() { result = this.getBaseType(_) }
+
+ Type getType() { result = s.getType() }
+
+ string getName() { result = s.getName() }
+ }
+
+ class FunctionDefinitionChildMapping extends NonExprChildMapping, FunctionDefinitionStmt {
+ override predicate relevantChild(Ast child) { none() }
+ }
+
+ class FunctionDefinitionCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "FunctionDefinitionCfgNode" }
+
+ override FunctionDefinitionChildMapping s;
+
+ override FunctionDefinitionStmt getStmt() { result = s }
+
+ FunctionBase getFunction() { result = s.getFunction() }
+ }
+
+ class ExprStmtChildMapping extends NonExprChildMapping, ExprStmt {
+ override predicate relevantChild(Ast child) { child = this.getExpr() }
+ }
- override PipelineChildMapping s;
+ class ExprStmtCfgNode extends StmtCfgNode {
+ override string getAPrimaryQlClass() { result = "ExprStmtCfgNode" }
- override Pipeline getStmt() { result = super.getStmt() }
+ override ExprStmtChildMapping s;
- final CmdBaseCfgNode getComponent(int i) { s.hasCfgChild(s.getComponent(i), this, result) }
+ override ExprStmt getStmt() { result = s }
- final CmdBaseCfgNode getAComponent() { s.hasCfgChild(s.getAComponent(), this, result) }
+ ExprCfgNode getExpr() { s.hasCfgChild(s.getExpr(), this, result) }
}
}
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/ControlFlowGraph.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/ControlFlowGraph.qll
index b986bafc9337..d8ec9bb88020 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/ControlFlowGraph.qll
+++ b/powershell/ql/lib/semmle/code/powershell/controlflow/ControlFlowGraph.qll
@@ -6,7 +6,6 @@ private import SuccessorTypes
private import internal.ControlFlowGraphImpl as CfgImpl
private import internal.Splitting as Splitting
private import internal.Completion
-private import internal.Scope
/**
* An AST node with an associated control-flow graph.
@@ -16,7 +15,16 @@ private import internal.Scope
* Note that module declarations are not themselves CFG scopes, as they are part of
* the CFG of the enclosing top-level or callable.
*/
-class CfgScope extends Scope instanceof CfgImpl::CfgScope { }
+class CfgScope extends Scope instanceof CfgImpl::CfgScope {
+ final CfgScope getOuterCfgScope() {
+ exists(Ast parent |
+ parent = this.getParent() and
+ result = CfgImpl::getCfgScope(parent)
+ )
+ }
+
+ Parameter getAParameter() { result = super.getAParameter() }
+}
/**
* A control flow node.
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Completion.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Completion.qll
index 31669a955ab8..68b602dfd93e 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Completion.qll
+++ b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Completion.qll
@@ -22,9 +22,9 @@ private newtype TCompletion =
TMatchingCompletion(Boolean b) or
TEmptinessCompletion(Boolean isEmpty)
-private predicate commandThrows(Cmd c, boolean unconditional) {
- c.getNamedArgument("ErrorAction").(StringConstExpr).getValue().getValue() = "Stop" and
- if c.getCommandName() = "Write-Error" then unconditional = true else unconditional = false
+private predicate commandThrows(CallExpr c, boolean unconditional) {
+ c.getNamedArgument("ErrorAction").getValue().asString() = "Stop" and
+ if c.getName() = "Write-Error" then unconditional = true else unconditional = false
}
pragma[noinline]
@@ -127,7 +127,7 @@ private predicate mustHaveMatchingCompletion(Ast n) { inMatchingContext(n) }
* that `n` evaluates to determines a true/false branch successor.
*/
private predicate inBooleanContext(Ast n) {
- n = any(IfStmt ifStmt).getACondition()
+ n = any(If ifStmt).getACondition()
or
n = any(WhileStmt whileStmt).getCondition()
or
@@ -165,10 +165,7 @@ private predicate inBooleanContext(Ast n) {
n = pipeline.getComponent(pipeline.getNumberOfComponents() - 1)
)
or
- exists(CmdExpr cmdExpr |
- inBooleanContext(cmdExpr) and
- n = cmdExpr.getExpr()
- )
+ n = any(ParenExpr parent | inBooleanContext(parent)).getExpr()
}
/**
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll
index 909545088fa2..25d0773b0c07 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll
@@ -8,6 +8,8 @@ private import codeql.controlflow.Cfg as CfgShared
private import codeql.util.Boolean
private import semmle.code.powershell.controlflow.ControlFlowGraph
private import Completion
+private import semmle.code.powershell.ast.internal.Raw.Raw as Raw
+private import semmle.code.powershell.ast.internal.TAst
private module CfgInput implements CfgShared::InputSig {
private import ControlFlowGraphImpl as Impl
@@ -51,11 +53,11 @@ private module CfgInput implements CfgShared::InputSig {
t instanceof Cfg::SuccessorTypes::ExitSuccessor
}
- private predicate id(Ast node1, Ast node2) { node1 = node2 }
+ private predicate id(Raw::Ast node1, Raw::Ast node2) { node1 = node2 }
- private predicate idOf(Ast node, int id) = equivalenceRelation(id/2)(node, id)
+ private predicate idOf(Raw::Ast node, int id) = equivalenceRelation(id/2)(node, id)
- int idOfAstNode(AstNode node) { idOf(node, result) }
+ int idOfAstNode(AstNode node) { idOf(toRawIncludingSynth(node), result) }
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }
}
@@ -78,7 +80,7 @@ private module ConditionalCompletionSplittingInput implements
import CfgShared::MakeWithSplitting
-class CfgScope extends Scope {
+class CfgScope extends ScriptBlock {
predicate entry(Ast first) { first(this, first) }
predicate exit(Ast last, Completion c) { last(this, last, c) }
@@ -94,9 +96,24 @@ predicate succExit(CfgScope scope, Ast last, Completion c) { scope.exit(last, c)
/** Defines the CFG by dispatch on the various AST types. */
module Trees {
- class ParameterBlockTree extends StandardPostOrderTree instanceof ParamBlock {
- override AstNode getChildNode(int i) {
- exists(Parameter p | p = super.getParameter(i) | result = p.getDefaultValue())
+ class ParameterTree extends ControlFlowTree instanceof Parameter {
+ final override predicate propagatesAbnormal(AstNode child) { child = super.getDefaultValue() }
+
+ final override predicate first(AstNode first) { first = this }
+
+ final override predicate last(AstNode last, Completion c) {
+ last(super.getDefaultValue(), last, c) and
+ completionIsNormal(c)
+ or
+ not super.hasDefaultValue() and
+ last = this and
+ completionIsSimple(c)
+ }
+
+ final override predicate succ(AstNode pred, AstNode succ, Completion c) {
+ pred = this and
+ first(super.getDefaultValue(), succ) and
+ completionIsSimple(c)
}
}
@@ -128,12 +145,6 @@ module Trees {
not exists(super.getEndBlock()) and
not exists(super.getProcessBlock()) and
not exists(super.getBeginBlock()) and
- last(super.getParamBlock(), last, c)
- or
- not exists(super.getEndBlock()) and
- not exists(super.getProcessBlock()) and
- not exists(super.getBeginBlock()) and
- not exists(super.getParamBlock()) and
// No blocks at all. We end where we started
this.succEntry(last, c)
}
@@ -141,22 +152,28 @@ module Trees {
override predicate succ(AstNode pred, AstNode succ, Completion c) {
this.succEntry(pred, c) and
(
- first(super.getParamBlock(), succ)
+ first(super.getParameter(0), succ)
or
- not exists(super.getParamBlock()) and
+ not exists(super.getAParameter()) and
first(super.getBeginBlock(), succ)
or
- not exists(super.getParamBlock()) and
+ not exists(super.getAParameter()) and
not exists(super.getBeginBlock()) and
first(super.getProcessBlock(), succ)
or
- not exists(super.getParamBlock()) and
+ not exists(super.getAParameter()) and
not exists(super.getBeginBlock()) and
not exists(super.getProcessBlock()) and
first(super.getEndBlock(), succ)
)
or
- last(super.getParamBlock(), pred, c) and
+ exists(int i |
+ last(super.getParameter(i), pred, c) and
+ completionIsNormal(c) and
+ first(super.getParameter(i + 1), succ)
+ )
+ or
+ last(super.getParameter(super.getNumberOfParameters() - 1), pred, c) and
completionIsNormal(c) and
(
first(super.getBeginBlock(), succ)
@@ -190,7 +207,7 @@ module Trees {
}
final override predicate propagatesAbnormal(AstNode child) {
- child = super.getParamBlock() or
+ child = super.getAParameter() or
child = super.getBeginBlock() or
child = super.getProcessBlock() or
child = super.getEndBlock()
@@ -198,7 +215,7 @@ module Trees {
}
class FunctionScriptBlockTree extends PreOrderTree, ScriptBlockTree {
- Function func;
+ FunctionBase func;
FunctionScriptBlockTree() { func.getBody() = this }
@@ -206,7 +223,7 @@ module Trees {
exists(Parameter p |
p =
rank[i + 1](Parameter cand, int j |
- cand.hasDefaultValue() and func.getFunctionParameter(j) = cand
+ cand.hasDefaultValue() and func.getParameter(j) = cand
|
cand order by j
) and
@@ -478,13 +495,11 @@ module Trees {
override AstNode getChildNode(int i) {
i = 0 and result = super.getQualifier()
or
- i = 1 and result = super.getMember()
+ i = 1 and result = super.getMemberExpr()
}
}
- class CmdParameterTree extends LeafTree instanceof CmdParameter { }
-
- class IfStmtTree extends PreOrderTree instanceof IfStmt {
+ class IfTree extends PostOrderTree instanceof If {
final override predicate propagatesAbnormal(AstNode child) {
child = super.getACondition()
or
@@ -493,17 +508,9 @@ module Trees {
child = super.getElse()
}
- final override predicate last(AstNode last, Completion c) {
- last(super.getAThen(), last, c)
- or
- last(super.getElse(), last, c)
- }
+ final override predicate first(AstNode first) { first(super.getCondition(0), first) }
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
- this = pred and
- first(super.getCondition(0), succ) and
- completionIsSimple(c)
- or
exists(int i, boolean value |
last(super.getCondition(i), pred, c) and value = c.(BooleanCompletion).getValue()
|
@@ -515,9 +522,21 @@ module Trees {
first(super.getCondition(i + 1), succ)
or
i = super.getNumberOfConditions() - 1 and
- first(super.getElse(), succ)
+ (
+ first(super.getElse(), succ)
+ or
+ not exists(super.getElse()) and
+ succ = this
+ )
)
)
+ or
+ (
+ last(super.getAThen(), pred, c) or
+ last(super.getElse(), pred, c)
+ ) and
+ completionIsNormal(c) and
+ succ = this
}
}
@@ -592,6 +611,12 @@ module Trees {
class VarAccessTree extends LeafTree instanceof VarAccess { }
+ class VarTree extends LeafTree instanceof Variable { }
+
+ class EnvVariableTree extends LeafTree instanceof EnvVariable { }
+
+ class AutomaticVariableTree extends LeafTree instanceof AutomaticVariable { }
+
class BinaryExprTree extends StandardPostOrderTree instanceof BinaryExpr {
override AstNode getChildNode(int i) {
i = 0 and result = super.getLeft()
@@ -607,7 +632,7 @@ module Trees {
class ScriptBlockExprTree extends LeafTree instanceof ScriptBlockExpr { }
class ConvertExprTree extends StandardPostOrderTree instanceof ConvertExpr {
- override AstNode getChildNode(int i) { i = 0 and result = super.getBase() }
+ override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
}
class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr {
@@ -619,13 +644,13 @@ module Trees {
}
class ParenExprTree extends StandardPostOrderTree instanceof ParenExpr {
- override AstNode getChildNode(int i) { i = 0 and result = super.getBase() }
+ override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
}
class TypeNameExprTree extends LeafTree instanceof TypeNameExpr { }
class ArrayLiteralTree extends StandardPostOrderTree instanceof ArrayLiteral {
- override AstNode getChildNode(int i) { result = super.getElement(i) }
+ override AstNode getChildNode(int i) { result = super.getExpr(i) }
}
class ArrayExprTree extends StandardPostOrderTree instanceof ArrayExpr {
@@ -671,7 +696,7 @@ module Trees {
class TypeConstraintTree extends LeafTree instanceof TypeConstraint { }
- class TypeTree extends LeafTree instanceof Type { }
+ class TypeDefinitionTree extends LeafTree instanceof TypeDefinitionStmt { }
class TryStmtBlock extends PreOrderTree instanceof TryStmt {
final override predicate propagatesAbnormal(AstNode child) { child = super.getFinally() }
@@ -745,34 +770,30 @@ module Trees {
}
}
- class CmdExprTree extends StandardPostOrderTree instanceof CmdExpr {
- override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
- }
-
- class CmdTree extends StandardPostOrderTree instanceof Cmd {
+ class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
override AstNode getChildNode(int i) {
- i = -1 and result = super.getCommand()
+ i = -2 and result = super.getQualifier()
+ or
+ i = -1 and result = super.getCallee()
or
result = super.getArgument(i)
}
}
+ class ExprStmtTree extends StandardPreOrderTree instanceof ExprStmt {
+ override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
+ }
+
class StringConstTree extends LeafTree instanceof StringConstExpr { }
class PipelineTree extends StandardPreOrderTree instanceof Pipeline {
override AstNode getChildNode(int i) { result = super.getComponent(i) }
}
- class InvokeMemberExprTree extends StandardPostOrderTree instanceof InvokeMemberExpr {
- override AstNode getChildNode(int i) {
- i = -1 and result = super.getQualifier()
- or
- result = super.getArgument(i)
- }
- }
-}
+ class FunctionDefinitionStmtTree extends LeafTree instanceof FunctionDefinitionStmt { }
-private import Scope
+ class LiteralTree extends LeafTree instanceof Literal { }
+}
cached
private CfgScope getCfgScopeImpl(Ast n) { result = scopeOf(n) }
diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Splitting.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Splitting.qll
index 012f284eb445..b2734c98194d 100644
--- a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Splitting.qll
+++ b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Splitting.qll
@@ -69,6 +69,8 @@ module ConditionalCompletionSplitting {
child = parent.(LogicalOrExpr).getAnOperand()
or
child = parent.(ConditionalExpr).getBranch(_)
+ or
+ child = parent.(ParenExpr).getExpr()
)
}
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/FlowSummary.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/FlowSummary.qll
index 0f236704fef0..4e1b38358f2a 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/FlowSummary.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/FlowSummary.qll
@@ -53,12 +53,12 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
* calls to a method with the same name are considered relevant.
*/
abstract class SimpleSummarizedCallable extends SummarizedCallable {
- Call c;
+ CallExpr c;
bindingset[this]
SimpleSummarizedCallable() { c.getName() = this }
- final override Call getACall() { result = c }
+ final override CallExpr getACall() { result = c }
- final override Call getACallSimple() { result = c }
+ final override CallExpr getACallSimple() { result = c }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/Ssa.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/Ssa.qll
index 7c0bd28dc107..e023162d437f 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/Ssa.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/Ssa.qll
@@ -6,11 +6,10 @@
* Provides classes for working with static single assignment (SSA) form.
*/
module Ssa {
- private import semmle.code.powershell.Cfg
private import powershell
+ private import semmle.code.powershell.Cfg
private import internal.SsaImpl as SsaImpl
- private import CfgNodes
- private import ExprNodes
+ private import CfgNodes::ExprNodes
/** A static single assignment (SSA) definition. */
class Definition extends SsaImpl::Definition {
@@ -23,8 +22,10 @@ module Ssa {
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i))
}
- /** Gets a control-flow node that reads the value of this SSA definition. */
- final AstCfgNode getARead() { result = SsaImpl::getARead(this) }
+ /**
+ * Gets a control-flow node that reads the value of this SSA definition.
+ */
+ final VarReadAccessCfgNode getARead() { result = SsaImpl::getARead(this) }
/**
* Gets a first control-flow node that reads the value of this SSA definition.
@@ -38,16 +39,14 @@ module Ssa {
* That is, a read that can reach the end of the enclosing CFG scope, or another
* SSA definition for the source variable, without passing through any other read.
*/
- final VarReadAccessCfgNode getALastRead() { SsaImpl::lastRead(this, result) }
+ deprecated final VarReadAccessCfgNode getALastRead() { SsaImpl::lastRead(this, result) }
/**
* Holds if `read1` and `read2` are adjacent reads of this SSA definition.
* That is, `read2` can be reached from `read1` without passing through
* another read.
*/
- final predicate hasAdjacentReads(
- VarReadAccessCfgNode read1, VarReadAccessCfgNode read2
- ) {
+ final predicate hasAdjacentReads(VarReadAccessCfgNode read1, VarReadAccessCfgNode read2) {
SsaImpl::adjacentReadPair(this, read1, read2)
}
@@ -91,7 +90,7 @@ module Ssa {
/**
* Holds if this SSA definition assigns `value` to the underlying variable.
*/
- predicate assigns(CfgNodes::StmtCfgNode value) {
+ predicate assigns(CfgNodes::ExprCfgNode value) {
exists(CfgNodes::StmtNodes::AssignStmtCfgNode a, BasicBlock bb, int i |
this.definesAt(_, bb, i) and
a = bb.getNode(i) and
@@ -104,19 +103,19 @@ module Ssa {
final override Location getLocation() { result = write.getLocation() }
}
- class ParameterDefinition extends Definition, SsaImpl::WriteDefinition {
- private Variable v;
+ /**
+ * An SSA definition that corresponds to the value of `this` upon entry to a method.
+ */
+ class ThisDefinition extends Definition, SsaImpl::WriteDefinition {
+ private ThisParameter v;
- ParameterDefinition() {
- exists(BasicBlock bb, int i |
- this.definesAt(v, bb, i) and
- SsaImpl::parameterWrite(bb, i, v)
- )
- }
+ ThisDefinition() { exists(BasicBlock bb, int i | this.definesAt(v, bb, i)) }
+
+ override ThisParameter getSourceVariable() { result = v }
- final override string toString() { result = " " + v }
+ final override string toString() { result = "self (" + v.getDeclaringScope() + ")" }
- final override Location getLocation() { result = v.getLocation() }
+ final override Location getLocation() { result = this.getControlFlowNode().getLocation() }
}
/**
@@ -138,7 +137,7 @@ module Ssa {
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
}
- /** A phi node. */
+ /** phi node. */
class PhiNode extends Definition, SsaImpl::PhiNode {
/** Gets an input of this phi node. */
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
@@ -148,7 +147,20 @@ module Ssa {
inp = SsaImpl::phiHasInputFromBlock(this, bb)
}
- override string toString() { result = "phi" }
+ private string getSplitString() {
+ result = this.getBasicBlock().getFirstNode().(CfgNodes::AstCfgNode).getSplitsString()
+ }
+
+ override string toString() {
+ exists(string prefix |
+ prefix = "[" + this.getSplitString() + "] "
+ or
+ not exists(this.getSplitString()) and
+ prefix = ""
+ |
+ result = prefix + "phi"
+ )
+ }
/**
* The location of a phi node is the same as the location of the first node
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll
index b27d24a051c6..d0e2e2601fbd 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll
@@ -31,9 +31,7 @@ abstract class EnvironmentVariableSource extends LocalFlowSource {
}
private class EnvironmentVariableEnv extends EnvironmentVariableSource {
- EnvironmentVariableEnv() {
- this.asExpr().getExpr().(VarReadAccess).getVariable() instanceof EnvVariable
- }
+ EnvironmentVariableEnv() { this.asExpr().getExpr() instanceof EnvVariable }
}
private class ExternalEnvironmentVariableSource extends EnvironmentVariableSource {
@@ -61,7 +59,7 @@ private class ExternalCommandLineArgumentSource extends CommandLineArgumentSourc
* A data flow source that represents the parameters of the `Main` method of a program.
*/
private class MainMethodArgumentSource extends CommandLineArgumentSource {
- MainMethodArgumentSource() { this.asParameter().getFunction() instanceof TopLevel }
+ MainMethodArgumentSource() { this.asParameter().getParent() instanceof TopLevelScriptBlock }
}
/**
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll
index 4c397fbdd9a6..6619cb9887d7 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll
@@ -5,6 +5,7 @@ private import DataFlowPublic
private import semmle.code.powershell.typetracking.internal.TypeTrackingImpl
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.powershell.dataflow.FlowSummary
+private import SsaImpl as SsaImpl
private import codeql.util.Boolean
private import codeql.util.Unit
@@ -39,10 +40,10 @@ abstract class LibraryCallable extends string {
LibraryCallable() { any() }
/** Gets a call to this library callable. */
- Call getACall() { none() }
+ CallExpr getACall() { none() }
/** Same as `getACall()` except this does not depend on the call graph or API graph. */
- Call getACallSimple() { none() }
+ CallExpr getACallSimple() { none() }
}
/** A callable defined in library code, which should be taken into account in type tracking. */
@@ -90,7 +91,7 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying source code call, if any. */
- abstract CfgNodes::CallCfgNode asCall();
+ abstract CfgNodes::ExprNodes::CallExprCfgNode asCall();
/** Gets a textual representation of this call. */
abstract string toString();
@@ -130,7 +131,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
- override CfgNodes::CallCfgNode asCall() { none() }
+ override CfgNodes::ExprNodes::CallExprCfgNode asCall() { none() }
override string toString() { result = "[summary] call to " + receiver + " in " + c }
@@ -138,11 +139,11 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
}
class NormalCall extends DataFlowCall, TNormalCall {
- private CfgNodes::CallCfgNode c;
+ private CfgNodes::ExprNodes::CallExprCfgNode c;
NormalCall() { this = TNormalCall(c) }
- override CfgNodes::CallCfgNode asCall() { result = c }
+ override CfgNodes::ExprNodes::CallExprCfgNode asCall() { result = c }
override DataFlowCallable getEnclosingCallable() { result = TCfgScope(c.getScope()) }
@@ -161,7 +162,7 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig {
start.(ObjectCreationNode).getObjectCreationNode().getConstructedTypeName() = typename and
exact = true
or
- start.asExpr().(CfgNodes::ExprNodes::TypeNameCfgNode).getTypeName() = typename and
+ start.asExpr().(CfgNodes::ExprNodes::TypeNameExprCfgNode).getName() = typename and
exact = true
or
start.asParameter().getStaticType() = typename and
@@ -195,7 +196,9 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig {
predicate filter(Node n, Unit u) { none() }
}
-private predicate qualifiedCall(CfgNodes::CallCfgNode call, Node receiver, string method) {
+private predicate qualifiedCall(
+ CfgNodes::ExprNodes::CallExprCfgNode call, Node receiver, string method
+) {
call.getQualifier() = receiver.asExpr() and
call.getName() = method
}
@@ -214,7 +217,7 @@ private Type getTypeWithName(string s, boolean exact) {
exact = false
}
-private CfgScope getTargetInstance(CfgNodes::CallCfgNode call) {
+private CfgScope getTargetInstance(CfgNodes::ExprNodes::CallExprCfgNode call) {
// TODO: Also match argument/parameter types
exists(Node receiver, string method, string typename, Type t, boolean exact |
qualifiedCall(call, receiver, method) and
@@ -236,7 +239,7 @@ class AdditionalCallTarget extends Unit {
/**
* Gets a viable target for `call`.
*/
- abstract DataFlowCallable viableTarget(CfgNodes::CallCfgNode call);
+ abstract DataFlowCallable viableTarget(CfgNodes::ExprNodes::CallExprCfgNode call);
}
/** Holds if `call` may resolve to the returned summarized library method. */
@@ -256,7 +259,7 @@ private module Cached {
cached
newtype TDataFlowCall =
- TNormalCall(CfgNodes::CallCfgNode c) or
+ TNormalCall(CfgNodes::ExprNodes::CallExprCfgNode c) or
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
@@ -283,7 +286,7 @@ private module Cached {
FlowSummaryImpl::ParsePositions::isParsedKeywordParameterPosition(_, name)
} or
TPositionalArgumentPosition(int pos, NamedSet ns) {
- exists(CfgNodes::CallCfgNode call |
+ exists(CfgNodes::ExprNodes::CallExprCfgNode call |
call = ns.getABindingCall() and
exists(call.getArgument(pos))
)
@@ -297,7 +300,7 @@ private module Cached {
TThisParameterPosition() or
TKeywordParameter(string name) { name = any(Argument p).getName() } or
TPositionalParameter(int pos, NamedSet ns) {
- exists(CfgNodes::CallCfgNode call |
+ exists(CfgNodes::ExprNodes::CallExprCfgNode call |
call = ns.getABindingCall() and
exists(call.getArgument(pos))
)
@@ -306,7 +309,7 @@ private module Cached {
// `ns.getABindingCall()`, but those parameters should still have
// positions since SSA depends on this.
// In particular, global scope is also an uncalled function.
- any(Parameter p).getIndexExcludingPipelines() = pos and
+ any(SsaImpl::NormalParameter p).getIndexExcludingPipelines() = pos and
ns.isEmpty()
} or
TPipelineParameter()
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPrivate.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPrivate.qll
index 1825df4bfbe1..c5aa29ceff98 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPrivate.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPrivate.qll
@@ -46,20 +46,12 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
override string toStringImpl() { result = this.getExprNode().toString() }
}
-private class StmtNodeImpl extends StmtNode, NodeImpl {
- override CfgScope getCfgScope() { result = this.getStmtNode().getStmt().getEnclosingScope() }
-
- override Location getLocationImpl() { result = this.getStmtNode().getLocation() }
-
- override string toStringImpl() { result = this.getStmtNode().toString() }
-}
-
/** Gets the SSA definition node corresponding to parameter `p`. */
pragma[nomagic]
SsaImpl::DefinitionExt getParameterDef(Parameter p) {
exists(EntryBasicBlock bb, int i |
- SsaImpl::parameterWrite(bb, i, p) and
- result.definesAt(p, bb, i, _)
+ bb.getNode(i).getAstNode() = p and
+ result.definesAt(_, bb, i, _)
)
}
@@ -76,8 +68,6 @@ module SsaFlow {
or
result.(Impl::ExprNode).getExpr() = n.asExpr()
or
- result.(Impl::ExprNode).getExpr() = n.asStmt()
- or
result.(Impl::ExprNode).getExpr() =
[n.(ProcessNode).getProcessBlock(), n.(ProcessPropertyByNameNode).getProcessBlock()]
or
@@ -99,15 +89,13 @@ module SsaFlow {
module LocalFlow {
pragma[nomagic]
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
- nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConditionalCfgNode).getABranch()
- or
- nodeFrom.asStmt() = nodeTo.asStmt().(CfgNodes::StmtNodes::AssignStmtCfgNode).getRightHandSide()
+ nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConditionalExprCfgNode).getABranch()
or
- nodeFrom.asExpr() = nodeTo.asStmt().(CfgNodes::StmtNodes::CmdExprCfgNode).getExpr()
+ nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::StmtNodes::AssignStmtCfgNode).getRightHandSide()
or
- nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConvertCfgNode).getBase()
+ nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConvertExprCfgNode).getSubExpr()
or
- nodeFrom.asStmt() = nodeTo.asExpr().(CfgNodes::ExprNodes::ParenCfgNode).getBase()
+ nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ParenExprCfgNode).getSubExpr()
or
exists(
CfgNodes::ExprNodes::ArrayExprCfgNode arrayExpr, EscapeContainer::EscapeContainer container
@@ -149,8 +137,6 @@ module LocalFlow {
predicate localMustFlowStep(Node nodeFrom, Node nodeTo) {
SsaFlow::localMustFlowStep(_, nodeFrom, nodeTo)
or
- nodeFrom.asStmt() = nodeTo.asStmt().(CfgNodes::StmtNodes::AssignStmtCfgNode).getRightHandSide()
- or
nodeFrom =
unique(FlowSummaryNode n1 |
FlowSummaryImpl::Private::Steps::summaryLocalStep(n1.getSummaryNode(),
@@ -167,7 +153,7 @@ module VariableCapture {
private predicate isProcessPropertyByNameNode(
PipelineByPropertyNameIteratorVariable iter, ProcessBlock pb
) {
- pb.getEnclosingScope() = iter.getDeclaringScope()
+ pb = iter.getProcessBlock()
}
/** A collection of cached types and predicates to be evaluated in the same stage. */
@@ -180,18 +166,21 @@ private module Cached {
TExprNode(CfgNodes::ExprCfgNode n) or
TStmtNode(CfgNodes::StmtCfgNode n) or
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
- TNormalParameterNode(Parameter p) or
+ TNormalParameterNode(SsaImpl::NormalParameter p) or
+ TThisParameterNode(Method m) or
+ TPipelineByPropertyNameParameterNode(PipelineByPropertyNameParameter p) or
+ TPipelineParamaterNode(PipelineParameter p) or
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) {
n instanceof CfgNodes::ExprNodes::ArgumentCfgNode
or
n instanceof CfgNodes::ExprNodes::QualifierCfgNode
or
- exists(CfgNodes::ExprNodes::MemberCfgNode member |
+ exists(CfgNodes::ExprNodes::MemberExprCfgNode member |
n = member.getQualifier() and
not member.isStatic()
)
or
- n = any(CfgNodes::ExprNodes::IndexCfgNode index).getBase()
+ n = any(CfgNodes::ExprNodes::IndexExprCfgNode index).getBase()
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TPreReturnNodeImpl(CfgNodes::AstCfgNode n, Boolean isArray) { isMultiReturned(n) } or
@@ -202,7 +191,6 @@ private module Cached {
isProcessPropertyByNameNode(iter, _)
} or
TScriptBlockNode(ScriptBlock scriptBlock) or
- TTypePathNode(int n, CfgNode cfg) { isTypePathNode(_, n, cfg) } or
TForbiddenRecursionGuard() {
none() and
// We want to prune irrelevant models before materialising data flow nodes, so types contributed
@@ -289,34 +277,12 @@ private module Cached {
TypeTrackingInput::withoutContentStepImpl(_, n, _)
}
- private predicate isAutomaticVariable(Node n) {
- n.asExpr().(CfgNodes::ExprNodes::VarReadAccessCfgNode).getVariable().getName() =
- [
- "args", "ConsoleFileName", "EnabledExperimentalFeatures", "Error", "Event", "EventArgs",
- "EventSubscriber", "ExecutionContext", "HOME", "Host", "input", "IsCoreCLR", "IsLinux",
- "IsMacOS", "IsWindows", "LASTEXITCODE", "MyInvocation", "NestedPromptLevel", "PID",
- "PROFILE", "PSBoundParameters", "PSCmdlet", "PSCommandPath", "PSCulture", "PSDebugContext",
- "PSEdition", "PSHOME", "PSItem", "PSScriptRoot", "PSSenderInfo", "PSUICulture",
- "PSVersionTable", "PWD", "Sender", "ShellId", "StackTrace"
- ]
- }
-
cached
predicate isLocalSourceNode(Node n) {
n instanceof ParameterNode
or
- isAutomaticVariable(n)
- or
// Expressions that can't be reached from another entry definition or expression
- (
- n instanceof ExprNode
- or
- exists(CfgNodes::StmtNodes::AssignStmtCfgNode assign | assign.getRightHandSide() = n.asStmt())
- or
- n.asStmt() instanceof CfgNodes::StmtNodes::CmdCfgNode
- or
- exists(CfgNodes::StmtNodes::PipelineCfgNode pipeline | n.asStmt() = pipeline.getAComponent())
- ) and
+ n instanceof ExprNode and
not reachedFromExprOrEntrySsaDef(n)
or
// Ensure all entry SSA definitions are local sources, except those that correspond
@@ -442,10 +408,12 @@ class SsaInputNode extends SsaNode {
override CfgScope getCfgScope() { result = node.getDefinitionExt().getBasicBlock().getScope() }
}
-private string getANamedArgument(CfgNodes::CallCfgNode c) { exists(c.getNamedArgument(result)) }
+private string getANamedArgument(CfgNodes::ExprNodes::CallExprCfgNode c) {
+ exists(c.getNamedArgument(result))
+}
private module NamedSetModule =
- QlBuiltins::InternSets;
+ QlBuiltins::InternSets;
private newtype NamedSet0 =
TEmptyNamedSet() or
@@ -475,7 +443,7 @@ class NamedSet extends NamedSet0 {
*
* NOTE: The `CfgNodes::CallCfgNode` may also provide more names.
*/
- CfgNodes::CallCfgNode getABindingCall() {
+ CfgNodes::ExprNodes::CallExprCfgNode getABindingCall() {
forex(string name | name = this.getAName() | exists(result.getNamedArgument(name)))
or
this.isEmpty() and
@@ -486,7 +454,7 @@ class NamedSet extends NamedSet0 {
* Gets a `Cmd` that provides exactly the named parameters represented by
* this set.
*/
- CfgNodes::CallCfgNode getAnExactBindingCall() {
+ CfgNodes::ExprNodes::CallExprCfgNode getAnExactBindingCall() {
forex(string name | name = this.getAName() | exists(result.getNamedArgument(name))) and
forex(string name | exists(result.getNamedArgument(name)) | name = this.getAName())
or
@@ -505,6 +473,11 @@ class NamedSet extends NamedSet0 {
NamedSet emptyNamedSet() { result.isEmpty() }
+SsaImpl::NormalParameter getNormalParameter(FunctionBase f, int index) {
+ result.getFunction() = f and
+ result.getIndexExcludingPipelines() = index
+}
+
private module ParameterNodes {
abstract class ParameterNodeImpl extends NodeImpl {
abstract Parameter getParameter();
@@ -524,18 +497,15 @@ private module ParameterNodes {
* flow graph.
*/
class NormalParameterNode extends ParameterNodeImpl, TNormalParameterNode {
- Parameter parameter;
+ SsaImpl::NormalParameter parameter;
NormalParameterNode() { this = TNormalParameterNode(parameter) }
override Parameter getParameter() { result = parameter }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
- parameter.getDeclaringScope() = c.asCfgScope() and
+ parameter.getEnclosingScope() = c.asCfgScope() and
(
- pos.isThis() and
- parameter.isThis()
- or
pos.isKeyword(parameter.getName())
or
// Given a function f with parameters x, y we map
@@ -549,7 +519,7 @@ private module ParameterNodes {
// 3. position(1, {})
// The interpretation of `position(i, S)` is the position of the i'th unnamed parameter when the
// keywords in S are specified.
- exists(int i, int j, string name, NamedSet ns, Function f |
+ exists(int i, int j, string name, NamedSet ns, FunctionBase f |
pos.isPositional(j, ns) and
parameter.getIndexExcludingPipelines() = i and
f = parameter.getFunction() and
@@ -560,29 +530,79 @@ private module ParameterNodes {
i -
count(int k, Parameter p |
k < i and
- p = f.getParameterExcludingPiplines(k) and
+ p = getNormalParameter(f, k) and
p.getName() = ns.getAName()
)
)
- or
- (parameter.isPipeline() or parameter.isPipelineByPropertyName()) and
- pos.isPipeline()
)
}
- override CfgScope getCfgScope() {
- result.getAParameter() = parameter or result.getThisParameter() = parameter
- }
+ override CfgScope getCfgScope() { result.getAParameter() = parameter }
override Location getLocationImpl() { result = parameter.getLocation() }
override string toStringImpl() { result = parameter.toString() }
}
- class PipelineByPropertyNameParameterNode extends NormalParameterNode {
- PipelineByPropertyNameParameterNode() { this.getParameter().isPipelineByPropertyName() }
+ class ThisParameterNode extends ParameterNodeImpl, TThisParameterNode {
+ Method m;
+
+ ThisParameterNode() { this = TThisParameterNode(m) }
+
+ override Parameter getParameter() { none() }
+
+ override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
+ m.getBody() = c.asCfgScope() and
+ pos.isThis()
+ }
+
+ override CfgScope getCfgScope() { result = m.getBody() }
+
+ override Location getLocationImpl() { result = m.getLocation() }
+
+ override string toStringImpl() { result = "this" }
+ }
+
+ class PipelineParamaterNode extends ParameterNodeImpl, TPipelineParamaterNode {
+ private PipelineParameter parameter;
- string getPropretyName() { result = this.getParameter().getName() }
+ PipelineParamaterNode() { this = TPipelineParamaterNode(parameter) }
+
+ override PipelineParameter getParameter() { result = parameter }
+
+ override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
+ pos.isPipeline() and // what about when it is applied as a normal parameter?
+ c.asCfgScope() = parameter.getEnclosingScope()
+ }
+
+ override CfgScope getCfgScope() { result = parameter.getEnclosingScope() }
+
+ override Location getLocationImpl() { result = this.getParameter().getLocation() }
+
+ override string toStringImpl() { result = this.getParameter().toString() }
+ }
+
+ class PipelineByPropertyNameParameterNode extends ParameterNodeImpl,
+ TPipelineByPropertyNameParameterNode
+ {
+ private PipelineByPropertyNameParameter parameter;
+
+ PipelineByPropertyNameParameterNode() { this = TPipelineByPropertyNameParameterNode(parameter) }
+
+ override PipelineParameter getParameter() { result = parameter }
+
+ override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
+ pos.isPipeline() and // what about when it is applied as a normal parameter?
+ c.asCfgScope() = parameter.getEnclosingScope()
+ }
+
+ override CfgScope getCfgScope() { result = parameter.getEnclosingScope() }
+
+ override Location getLocationImpl() { result = this.getParameter().getLocation() }
+
+ override string toStringImpl() { result = this.getParameter().toString() }
+
+ string getPropertyName() { result = parameter.getPropertyName() }
}
/** A parameter for a library callable with a flow summary. */
@@ -628,7 +648,9 @@ abstract class ArgumentNode extends Node {
/** Holds if this argument occurs at the given position in the given call. */
abstract predicate argumentOf(DataFlowCall call, ArgumentPosition pos);
- abstract predicate sourceArgumentOf(CfgNodes::CallCfgNode call, ArgumentPosition pos);
+ abstract predicate sourceArgumentOf(
+ CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
+ );
/** Gets the call in which this node is an argument. */
final DataFlowCall getCall() { this.argumentOf(result, _) }
@@ -644,7 +666,9 @@ module ArgumentNodes {
this.sourceArgumentOf(call.asCall(), pos)
}
- override predicate sourceArgumentOf(CfgNodes::CallCfgNode call, ArgumentPosition pos) {
+ override predicate sourceArgumentOf(
+ CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
+ ) {
arg.getCall() = call and
(
pos.isKeyword(arg.getName())
@@ -654,32 +678,46 @@ module ArgumentNodes {
ns.getAnExactBindingCall() = call and
pos.isPositional(i, ns)
)
- or
- arg.isQualifier() and
- pos.isThis()
)
}
}
- private predicate isPipelineInput(
- CfgNodes::StmtNodes::CmdBaseCfgNode input, CfgNodes::StmtNodes::CmdBaseCfgNode consumer
- ) {
- exists(CfgNodes::StmtNodes::PipelineCfgNode pipeline, int i |
+ class ThisArgumentNode extends ArgumentNode {
+ CfgNodes::ExprNodes::QualifierCfgNode qual;
+
+ ThisArgumentNode() { this.asExpr() = qual }
+
+ override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
+ this.sourceArgumentOf(call.asCall(), pos)
+ }
+
+ override predicate sourceArgumentOf(
+ CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
+ ) {
+ qual.getCall() = call and
+ pos.isThis()
+ }
+ }
+
+ private predicate isPipelineInput(CfgNodes::ExprCfgNode input, CfgNodes::ExprCfgNode consumer) {
+ exists(CfgNodes::ExprNodes::PipelineCfgNode pipeline, int i |
input = pipeline.getComponent(i) and
consumer = pipeline.getComponent(i + 1)
)
}
- class PipelineArgumentNode extends ArgumentNode, StmtNode {
- CfgNodes::StmtNodes::CmdBaseCfgNode consumer;
+ class PipelineArgumentNode extends ArgumentNode, ExprNode {
+ CfgNodes::ExprCfgNode consumer;
- PipelineArgumentNode() { isPipelineInput(this.getStmtNode(), consumer) }
+ PipelineArgumentNode() { isPipelineInput(this.getExprNode(), consumer) }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
this.sourceArgumentOf(call.asCall(), pos)
}
- override predicate sourceArgumentOf(CfgNodes::CallCfgNode call, ArgumentPosition pos) {
+ override predicate sourceArgumentOf(
+ CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
+ ) {
call = consumer and
pos.isPipeline()
}
@@ -697,7 +735,11 @@ module ArgumentNodes {
call.(SummaryCall).getReceiver() = receiver and pos = pos_
}
- override predicate sourceArgumentOf(CfgNodes::CallCfgNode call, ArgumentPosition pos) { none() }
+ override predicate sourceArgumentOf(
+ CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
+ ) {
+ none()
+ }
}
}
@@ -715,11 +757,7 @@ private module EscapeContainer {
private module ReturnContainerInterpreter implements InterpretAstInputSig {
class T = CfgNodes::AstCfgNode;
- T interpret(Ast a) {
- result.(CfgNodes::ExprCfgNode).getExpr() = a
- or
- result.(CfgNodes::StmtCfgNode).getStmt() = a.(Cmd)
- }
+ T interpret(Ast a) { result.(CfgNodes::ExprCfgNode).getExpr() = a } // TODO: Recutse into expr-to-stmt conversions
}
class EscapeContainer extends AstEscape::Element {
@@ -818,16 +856,16 @@ predicate jumpStep(Node pred, Node succ) {
* content `c`.
*/
predicate storeStep(Node node1, ContentSet c, Node node2) {
- exists(CfgNodes::ExprNodes::MemberCfgWriteAccessNode var, Content::FieldContent fc |
+ exists(CfgNodes::ExprNodes::MemberExprWriteAccessCfgNode var, Content::FieldContent fc |
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = var.getQualifier() and
- node1.asStmt() = var.getAssignStmt().getRightHandSide() and
+ node1.asExpr() = var.getAssignStmt().getRightHandSide() and
fc.getName() = var.getMemberName() and
c.isSingleton(fc)
)
or
- exists(CfgNodes::ExprNodes::IndexCfgWriteNode var, CfgNodes::ExprCfgNode e |
+ exists(CfgNodes::ExprNodes::IndexExprWriteAccessCfgNode var, CfgNodes::ExprCfgNode e |
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = var.getBase() and
- node1.asStmt() = var.getAssignStmt().getRightHandSide() and
+ node1.asExpr() = var.getAssignStmt().getRightHandSide() and
e = var.getIndex()
|
exists(Content::KnownElementContent ec |
@@ -840,13 +878,13 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
)
or
exists(Content::KnownElementContent ec, int index |
- node2.asExpr().(CfgNodes::ExprNodes::ArrayLiteralCfgNode).getElement(index) = node1.asExpr() and
+ node2.asExpr().(CfgNodes::ExprNodes::ArrayLiteralCfgNode).getExpr(index) = node1.asExpr() and
c.isKnownOrUnknownElement(ec) and
index = ec.getIndex().asInt()
)
or
exists(CfgNodes::ExprCfgNode key |
- node2.asExpr().(CfgNodes::ExprNodes::HashTableCfgNode).getElement(key) = node1.asStmt()
+ node2.asExpr().(CfgNodes::ExprNodes::HashTableExprCfgNode).getValueFromKey(key) = node1.asExpr()
|
exists(Content::KnownElementContent ec |
c.isKnownOrUnknownElement(ec) and
@@ -887,14 +925,14 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
* Holds if there is a read step of content `c` from `node1` to `node2`.
*/
predicate readStep(Node node1, ContentSet c, Node node2) {
- exists(CfgNodes::ExprNodes::MemberCfgReadAccessNode var, Content::FieldContent fc |
+ exists(CfgNodes::ExprNodes::MemberExprReadAccessCfgNode var, Content::FieldContent fc |
node2.asExpr() = var and
node1.asExpr() = var.getQualifier() and
fc.getName() = var.getMemberName() and
c.isSingleton(fc)
)
or
- exists(CfgNodes::ExprNodes::IndexCfgReadNode var, CfgNodes::ExprCfgNode e |
+ exists(CfgNodes::ExprNodes::IndexExprReadAccessCfgNode var, CfgNodes::ExprCfgNode e |
node2.asExpr() = var and
node1.asExpr() = var.getBase() and
e = var.getIndex()
@@ -915,7 +953,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
)
or
c.isAnyElement() and
- exists(SsaImpl::DefinitionExt def, ProcessNode processNode, LocalScopeVariable iterator |
+ exists(SsaImpl::DefinitionExt def, ProcessNode processNode, Variable iterator |
processNode = node1 and iterator = def.getSourceVariable()
|
processNode.getIteratorVariable() = iterator and
@@ -937,8 +975,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
or
exists(Content::KnownElementContent ec, SsaImpl::DefinitionExt def |
c.isSingleton(ec) and
- node1.(PipelineByPropertyNameParameterNode).getPropretyName() = ec.getIndex().asString() and
- def.getSourceVariable() = node1.(PipelineByPropertyNameParameterNode).getParameter() and
+ node1.(PipelineByPropertyNameParameterNode).getPropertyName() = ec.getIndex().asString() and
+ def = SsaImpl::getParameterDef(node1.(PipelineByPropertyNameParameterNode).getParameter()) and
SsaImpl::firstRead(def, node2.asExpr())
)
or
@@ -1163,64 +1201,6 @@ class ScriptBlockNode extends TScriptBlockNode, NodeImpl {
override predicate nodeIsHidden() { any() }
}
-private predicate isTypePathNode(string type, int n, CfgNode cfg) {
- exists(CfgNodes::ExprNodes::TypeNameCfgNode typeName, string s |
- cfg = typeName and
- type = typeName.getTypeName() and
- s = type.splitAt(".", n)
- )
- or
- exists(CfgNodes::StmtNodes::CmdCfgNode cmd, string s |
- cfg = cmd.getCommand() and
- type = cmd.getNamespaceQualifier() and
- s = type.splitAt(".", n)
- )
-}
-
-/**
- * A dataflow node that represents a component of a type or module path.
- *
- * For example, `System`, `System.Management`, `System.Management.Automation`,
- * and `System.Management.Automation.PowerShell` in the type
- * name `[System.Management.Automation.PowerShell]`.
- */
-class TypePathNodeImpl extends TTypePathNode, NodeImpl {
- int n;
- CfgNode cfg;
-
- TypePathNodeImpl() { this = TTypePathNode(n, cfg) }
-
- string getType() { isTypePathNode(result, n, cfg) }
-
- predicate isComplete() { not exists(this.getNext()) }
-
- int getIndex() { result = n }
-
- string getComponent() { result = this.getType().splitAt(".", n) }
-
- override CfgScope getCfgScope() { result = cfg.getScope() }
-
- override Location getLocationImpl() { result = cfg.getLocation() }
-
- override string toStringImpl() {
- not exists(this.getPrev()) and
- result = this.getComponent()
- or
- result = this.getPrev() + "." + this.getComponent()
- }
-
- override predicate nodeIsHidden() { any() }
-
- TypePathNodeImpl getNext() { result = TTypePathNode(n + 1, cfg) }
-
- TypePathNodeImpl getPrev() { result.getNext() = this }
-
- TypePathNodeImpl getConstant(string s) {
- s = result.getComponent() and
- result = this.getNext()
- }
-}
-
/** A node that performs a type cast. */
class CastNode extends Node {
CastNode() { none() }
@@ -1250,16 +1230,19 @@ predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() }
newtype LambdaCallKind = TLambdaCallKind()
-private class CmdName extends StringConstExpr {
- CmdName() { this = any(Cmd c).getCmdName() }
+private class CmdName extends CfgNodes::ExprNodes::StringLiteralExprCfgNode {
+ CmdName() { this = any(CfgNodes::ExprNodes::CallExprCfgNode c).getCallee() }
- string getName() { result = this.getValue().getValue() }
+ string getName() { result = this.getValueString() }
}
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
- creation.asExpr().getExpr().(CmdName).getName() = c.asCfgScope().getEnclosingFunction().getName() and
- exists(kind)
+ exists(kind) and
+ exists(FunctionBase f |
+ f.getBody() = c.asCfgScope() and
+ creation.asExpr().(CmdName).getName() = f.getName()
+ )
}
/**
@@ -1267,7 +1250,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
* where `receiver` is the lambda expression.
*/
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
- call.asCall().getCommand() = receiver.asExpr() and exists(kind)
+ call.asCall().getCallee() = receiver.asExpr() and exists(kind)
}
/** Extra data-flow steps needed for lambda flow analysis. */
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPublic.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPublic.qll
index b8ae6a48e385..7848fb6e2a7d 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPublic.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowPublic.qll
@@ -13,8 +13,6 @@ class Node extends TNode {
/** Gets the expression corresponding to this node, if any. */
CfgNodes::ExprCfgNode asExpr() { result = this.(ExprNode).getExprNode() }
- CfgNodes::StmtCfgNode asStmt() { result = this.(StmtNode).getStmtNode() }
-
ScriptBlock asCallable() { result = this.(CallableNode).asCallableAstNode() }
/** Gets the parameter corresponding to this node, if any. */
@@ -69,22 +67,6 @@ class ExprNode extends AbstractAstNode, TExprNode {
CfgNodes::ExprCfgNode getExprNode() { result = n }
}
-/**
- * A statement, viewed as a node in a data flow graph.
- *
- * Note that because of control-flow splitting, one `Stmt` may correspond
- * to multiple `StmtNode`s, just like it may correspond to multiple
- * `ControlFlow::Node`s.
- */
-class StmtNode extends AbstractAstNode, TStmtNode {
- override CfgNodes::StmtCfgNode n;
-
- StmtNode() { this = TStmtNode(n) }
-
- /** Gets the expression corresponding to this node. */
- CfgNodes::StmtCfgNode getStmtNode() { result = n }
-}
-
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
@@ -193,21 +175,6 @@ class PostUpdateNode extends Node {
Node getPreUpdateNode() { result = pre }
}
-/**
- * A dataflow node that represents a component of a type or module path.
- *
- * For example, `System`, `System.Management`, `System.Management.Automation`,
- * and `System.Management.Automation.PowerShell` in the type
- * name `[System.Management.Automation.PowerShell]`.
- */
-class TypePathNode extends Node instanceof TypePathNodeImpl {
- string getComponent() { result = super.getComponent() }
-
- TypePathNode getConstant(string s) { result = super.getConstant(s) }
-
- API::Node track() { result = API::mod(super.getType(), super.getIndex()) }
-}
-
cached
private module Cached {
cached
@@ -247,9 +214,6 @@ private import Cached
/** Gets a node corresponding to expression `e`. */
ExprNode exprNode(CfgNodes::ExprCfgNode e) { result.getExprNode() = e }
-/** Gets a node corresponding to statement `s`. */
-StmtNode stmtNode(CfgNodes::StmtCfgNode e) { result.getStmtNode() = e }
-
/**
* Gets the node corresponding to the value of parameter `p` at function entry.
*/
@@ -437,27 +401,34 @@ module BarrierGuard {
*
* For example, `[Foo]::new()` or `New-Object Foo`.
*/
-class ObjectCreationNode extends Node {
- CfgNodes::ObjectCreationCfgNode objectCreation;
+class ObjectCreationNode extends ExprNode {
+ CfgNodes::ExprNodes::ObjectCreationCfgNode objectCreation;
- ObjectCreationNode() {
- this.asExpr() = objectCreation
- or
- this.asStmt() = objectCreation
+ ObjectCreationNode() { this.getExprNode() = objectCreation }
+
+ final CfgNodes::ExprNodes::ObjectCreationCfgNode getObjectCreationNode() {
+ result = objectCreation
}
- final CfgNodes::ObjectCreationCfgNode getObjectCreationNode() { result = objectCreation }
+ /**
+ * Gets the node corresponding to the expression that decides which type
+ * to allocate.
+ *
+ * For example, in `[Foo]::new()`, this would be `Foo`, and in
+ * `New-Object Foo`, this would be `Foo`.
+ */
+ Node getConstructedTypeNode() { result.asExpr() = objectCreation.getConstructedTypeExpr() }
string getConstructedTypeName() { result = this.getObjectCreationNode().getConstructedTypeName() }
}
/** A call, viewed as a node in a data flow graph. */
-class CallNode extends AstNode {
- CfgNodes::CallCfgNode call;
+class CallNode extends ExprNode {
+ CfgNodes::ExprNodes::CallExprCfgNode call;
CallNode() { call = this.getCfgNode() }
- CfgNodes::CallCfgNode getCallNode() { result = call }
+ CfgNodes::ExprNodes::CallExprCfgNode getCallNode() { result = call }
string getName() { result = call.getName() }
@@ -478,22 +449,33 @@ class CallNode extends AstNode {
* Note that this predicate doesn't get the pipeline argument, if any.
*/
Node getAnArgument() { result.asExpr() = call.getAnArgument() }
-
- int getNumberOfArguments() { result = call.getNumberOfArguments() }
}
/** A call to operator `&`, viwed as a node in a data flow graph. */
class CallOperatorNode extends CallNode {
- override CfgNodes::StmtNodes::CallOperatorCfgNode call;
+ override CfgNodes::ExprNodes::CallOperatorCfgNode call;
- Node getCommand() { result.asExpr() = call.getCommand() }
+ Node getCommand() { result.asExpr() = call.getCommand() } // TODO: Alternatively, we could remap calls to & as command expressions.
}
/** A use of a type name, viewed as a node in a data flow graph. */
class TypeNameNode extends ExprNode {
- override CfgNodes::ExprNodes::TypeNameCfgNode n;
+ override CfgNodes::ExprNodes::TypeNameExprCfgNode n;
+
+ override CfgNodes::ExprNodes::TypeNameExprCfgNode getExprNode() { result = n }
+
+ string getName() { result = n.getName() }
+
+ predicate isQualified() { n.isQualified() }
+
+ string getNamespace() { result = n.getNamespace() }
+
+ string getPossiblyQualifiedName() { result = n.getPossiblyQualifiedName() }
+}
- final override CfgNodes::ExprNodes::TypeNameCfgNode getExprNode() { result = n }
+/** A use of a qualified type name, viewed as a node in a data flow graph. */
+class QualifiedTypeNameNode extends TypeNameNode {
+ override CfgNodes::ExprNodes::QualifiedTypeNameExprCfgNode n;
- string getTypeName() { result = n.getTypeName() }
+ final override CfgNodes::ExprNodes::QualifiedTypeNameExprCfgNode getExprNode() { result = n }
}
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/SsaImpl.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/SsaImpl.qll
index deb814e50854..d9dceb4d27a4 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/SsaImpl.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/SsaImpl.qll
@@ -19,7 +19,7 @@ module SsaInput implements SsaImplCommon::InputSig {
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
- class SourceVariable = LocalScopeVariable;
+ class SourceVariable = Variable;
/**
* Holds if the statement at index `i` of basic block `bb` contains a write to variable `v`.
@@ -27,23 +27,21 @@ module SsaInput implements SsaImplCommon::InputSig {
*/
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
(
- uninitializedWrite(bb, i, v)
+ exists(Scope scope | scope = v.(ThisParameter).getDeclaringScope() |
+ // We consider the `this` variable to have a single write at the entry to a method block
+ scope = bb.(BasicBlocks::EntryBasicBlock).getScope() and
+ i = 0
+ )
or
- parameterWrite(bb, i, v)
+ uninitializedWrite(bb, i, v)
or
variableWriteActual(bb, i, v, _)
- or
- pipelineIteratorWrite(bb, i, v)
) and
certain = true
}
- predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
- (
- variableReadActual(bb, i, v)
- or
- pipelineRead(bb, i, v)
- ) and
+ predicate variableRead(BasicBlock bb, int i, Variable v, boolean certain) {
+ variableReadActual(bb, i, v) and
certain = true
}
}
@@ -61,101 +59,20 @@ class PhiNode = Impl::PhiNode;
module Consistency = Impl::Consistency;
/** Holds if `v` is uninitialized at index `i` in entry block `bb`. */
-predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
- v.getDeclaringScope() = bb.getScope() and
- i = -1
-}
-
-predicate pipelineIteratorWrite(Cfg::BasicBlock bb, int i, LocalScopeVariable v) {
- exists(ProcessBlockCfgNode process | process = bb.getNode(i) |
- v.(PipelineIteratorVariable).getProcessBlock() = process.getAstNode()
- or
- v.(PipelineByPropertyNameIteratorVariable).getProcessBlock() = process.getAstNode()
- )
-}
-
-/**
- * Gets index of `p` in a version of the enclosing function where the parameter
- * list is reversed.
- *
- * For example, given
- * ```ps
- * function f($a, $b) { ... }
- * ```
- * the inverted index of `$a` is 1, and the inverted index of `$b` is 0.
- *
- * The inverted index of `$this` is always always the number of
- * parameters (excluding `this`).
- */
-private int getInvertedIndex(Parameter p) {
- p.isThis() and
- result = p.getFunction().getNumberOfParameters()
- or
- exists(int i |
- p.getIndex() = i or
- p.hasParameterBlock(_, i)
- |
- result = p.getFunction().getNumberOfParameters() - i - 1
- )
-}
-
-/**
- * Holds if the the SSA definition of `p` should be placed at index `i` in
- * block `bb`. Note that the index may be negative.
- */
-predicate parameterWrite(Cfg::EntryBasicBlock bb, int i, Parameter p) {
- exists(Function f |
- f.getEntryBasicBlock() = bb and
- p.getFunction() = f and
- // If the enclosing function has 2 parameters we map the index of parameter
- // 0 to -2, the index of parameter 1 to -1.
- i = -getInvertedIndex(p) - 1
- )
-}
-
-private LocalScopeVariable getPipelineIterator(LocalScopeVariable pipelineParam) {
- result.(PipelineIteratorVariable).getProcessBlock().getScriptBlock() =
- pipelineParam.(PipelineParameter).getDeclaringScope()
- or
- result.(PipelineByPropertyNameIteratorVariable).getParameter() =
- pipelineParam.(PipelineByPropertyNameParameter)
-}
-
-private predicate isPipelineIteratorVarAccess(VarAccessCfgNode va) {
- (
- va.getVariable() instanceof PipelineParameter or
- va.getVariable() instanceof PipelineByPropertyNameParameter
- ) and
- va.getAstNode().getParent*() instanceof ProcessBlock
+predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, Variable v) {
+ bb.getNode(i).getAstNode() = v
}
/** Holds if `v` is read at index `i` in basic block `bb`. */
-private predicate variableReadActual(Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v) {
- exists(VarReadAccessCfgNode read, SsaInput::SourceVariable w |
- read.getVariable() = w and read = bb.getNode(i)
- |
- if isPipelineIteratorVarAccess(read) then v = getPipelineIterator(w) else v = w
- )
-}
-
-private predicate pipelineRead(Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v) {
- exists(ProcessBlockCfgNode process | process = bb.getNode(i) |
- v = process.getPipelineParameter() or
- v = process.getAPipelineByPropertyNameParameter()
+private predicate variableReadActual(Cfg::BasicBlock bb, int i, Variable v) {
+ exists(VarReadAccess read |
+ read.getVariable() = v and
+ read = bb.getNode(i).getAstNode()
)
}
pragma[noinline]
-private predicate adjacentDefRead(
- Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
- SsaInput::SourceVariable v
-) {
- Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
- v = def.getSourceVariable()
-}
-
-pragma[noinline]
-private predicate adjacentDefReadExt(
+deprecated private predicate adjacentDefReadExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
SsaInput::SourceVariable v
) {
@@ -163,23 +80,7 @@ private predicate adjacentDefReadExt(
v = def.getSourceVariable()
}
-private predicate adjacentDefReachesRead(
- Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
-) {
- exists(SsaInput::SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
- def.definesAt(v, bb1, i1)
- or
- SsaInput::variableRead(bb1, i1, v, true)
- )
- or
- exists(SsaInput::BasicBlock bb3, int i3 |
- adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
- SsaInput::variableRead(bb3, i3, _, false) and
- Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
- )
-}
-
-private predicate adjacentDefReachesReadExt(
+deprecated private predicate adjacentDefReachesReadExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
exists(SsaInput::SourceVariable v | adjacentDefReadExt(def, bb1, i1, bb2, i2, v) |
@@ -195,16 +96,7 @@ private predicate adjacentDefReachesReadExt(
)
}
-/** Same as `adjacentDefRead`, but skips uncertain reads. */
-pragma[nomagic]
-private predicate adjacentDefSkipUncertainReads(
- Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
-) {
- adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
- SsaInput::variableRead(bb2, i2, _, true)
-}
-
-private predicate adjacentDefReachesUncertainReadExt(
+deprecated private predicate adjacentDefReachesUncertainReadExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
adjacentDefReachesReadExt(def, bb1, i1, bb2, i2) and
@@ -213,7 +105,9 @@ private predicate adjacentDefReachesUncertainReadExt(
/** Same as `lastRefRedef`, but skips uncertain reads. */
pragma[nomagic]
-private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, SsaInput::BasicBlock bb, int i) {
+deprecated private predicate lastRefSkipUncertainReadsExt(
+ DefinitionExt def, SsaInput::BasicBlock bb, int i
+) {
Impl::lastRef(def, bb, i) and
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
or
@@ -223,6 +117,20 @@ private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, SsaInput::Basi
)
}
+/**
+ * Holds if the read of `def` at `read` may be a last read. That is, `read`
+ * can either reach another definition of the underlying source variable or
+ * the end of the CFG scope, without passing through another non-pseudo read.
+ */
+pragma[nomagic]
+deprecated predicate lastRead(Definition def, VarReadAccessCfgNode read) {
+ exists(Cfg::BasicBlock bb, int i |
+ lastRefSkipUncertainReadsExt(def, bb, i) and
+ variableReadActual(bb, i, _) and
+ read = bb.getNode(i)
+ )
+}
+
cached
private module Cached {
/**
@@ -231,12 +139,11 @@ private module Cached {
*/
cached
predicate variableWriteActual(
- Cfg::BasicBlock bb, int i, SsaInput::SourceVariable v, VarWriteAccessCfgNode write
+ Cfg::BasicBlock bb, int i, Variable v, VarWriteAccessCfgNode write
) {
- exists(Cfg::CfgNode n, SsaInput::SourceVariable w |
- write.getVariable() = w and
- n = bb.getNode(i) and
- if isPipelineIteratorVarAccess(write) then v = getPipelineIterator(w) else v = w
+ exists(Cfg::CfgNode n |
+ write.getVariable() = v and
+ n = bb.getNode(i)
|
write.isExplicitWrite(n)
or
@@ -246,10 +153,10 @@ private module Cached {
}
cached
- AstCfgNode getARead(Definition def) {
- exists(SsaInput::SourceVariable v, Cfg::BasicBlock bb, int i |
+ VarReadAccessCfgNode getARead(Definition def) {
+ exists(Variable v, Cfg::BasicBlock bb, int i |
Impl::ssaDefReachesRead(v, def, bb, i) and
- SsaInput::variableRead(bb, i, v, true) and
+ variableReadActual(bb, i, v) and
result = bb.getNode(i)
)
}
@@ -267,11 +174,7 @@ private module Cached {
*/
cached
predicate firstRead(Definition def, VarReadAccessCfgNode read) {
- exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
- def.definesAt(_, bb1, i1) and
- adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and
- read = bb2.getNode(i2)
- )
+ exists(Cfg::BasicBlock bb, int i | Impl::firstUse(def, bb, i, true) and read = bb.getNode(i))
}
/**
@@ -281,28 +184,14 @@ private module Cached {
*/
cached
predicate adjacentReadPair(Definition def, VarReadAccessCfgNode read1, VarReadAccessCfgNode read2) {
- exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
+ exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2, Variable v |
+ Impl::ssaDefReachesRead(v, def, bb1, i1) and
+ Impl::adjacentUseUse(bb1, i1, bb2, i2, v, true) and
read1 = bb1.getNode(i1) and
- variableReadActual(bb1, i1, _) and
- adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and
read2 = bb2.getNode(i2)
)
}
- /**
- * Holds if the read of `def` at `read` may be a last read. That is, `read`
- * can either reach another definition of the underlying source variable or
- * the end of the CFG scope, without passing through another non-pseudo read.
- */
- cached
- predicate lastRead(Definition def, VarReadAccessCfgNode read) {
- exists(Cfg::BasicBlock bb, int i |
- lastRefSkipUncertainReadsExt(def, bb, i) and
- variableReadActual(bb, i, _) and
- read = bb.getNode(i)
- )
- }
-
cached
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
Impl::uncertainWriteDefinitionInput(def, result)
@@ -326,8 +215,14 @@ private module Cached {
cached // nothing is actually cached
module BarrierGuard {
+ private predicate guardChecksAdjTypes(
+ DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, boolean branch
+ ) {
+ guardChecks(g, e, branch)
+ }
+
private Node getABarrierNodeImpl() {
- none() // TODO
+ result = DataFlowIntegrationImpl::BarrierGuard::getABarrierNode()
}
predicate getABarrierNode = getABarrierNodeImpl/0;
@@ -346,7 +241,7 @@ import Cached
* Only intended for internal use.
*/
class DefinitionExt extends Impl::DefinitionExt {
- AstCfgNode getARead() { result = getARead(this) }
+ VarReadAccessCfgNode getARead() { result = getARead(this) }
override string toString() { result = this.(Ssa::Definition).toString() }
@@ -367,29 +262,64 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
/** Gets the SSA definition node corresponding to parameter `p`. */
pragma[nomagic]
DefinitionExt getParameterDef(Parameter p) {
- exists(Cfg::EntryBasicBlock bb, int i |
- parameterWrite(bb, i, p) and
- result.definesAt(p, bb, i, _)
+ exists(Cfg::BasicBlock bb, int i |
+ bb.getNode(i).getAstNode() = p and
+ result.definesAt(_, bb, i, _)
)
}
-private newtype TParameterExt = TNormalParameter(Parameter p)
+private Parameter getANonPipelineParameter(FunctionBase f) {
+ result = f.getAParameter() and
+ not result instanceof PipelineParameter and
+ not result instanceof PipelineByPropertyNameParameter
+}
+
+class NormalParameter extends Parameter {
+ NormalParameter() {
+ not this instanceof PipelineParameter and
+ not this instanceof PipelineByPropertyNameParameter
+ }
+
+ int getIndexExcludingPipelines() {
+ exists(FunctionBase f |
+ f = this.getFunction() and
+ this =
+ rank[result + 1](int index, Parameter p |
+ p = getANonPipelineParameter(f) and index = p.getIndex()
+ |
+ p order by index
+ )
+ )
+ }
+}
+
+private newtype TParameterExt =
+ TNormalParameter(NormalParameter p) or
+ TSelfMethodParameter(Method m)
/** A normal parameter or an implicit `self` parameter. */
class ParameterExt extends TParameterExt {
- Parameter asParameter() { this = TNormalParameter(result) }
+ NormalParameter asParameter() { this = TNormalParameter(result) }
- predicate isInitializedBy(WriteDefinition def) { def = getParameterDef(this.asParameter()) }
+ Method asThis() { this = TSelfMethodParameter(result) }
- string toString() { result = this.asParameter().toString() }
+ predicate isInitializedBy(WriteDefinition def) {
+ def = getParameterDef(this.asParameter())
+ or
+ def.(Ssa::ThisDefinition).getSourceVariable().getDeclaringScope() = this.asThis().(Scope)
+ }
+
+ string toString() { result = [this.asParameter().toString(), this.asThis().toString()] }
- Location getLocation() { result = this.asParameter().getLocation() }
+ Location getLocation() {
+ result = [this.asParameter().getLocation(), this.asThis().getLocation()]
+ }
}
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
class Parameter = ParameterExt;
- class Expr extends Cfg::CfgNodes::AstCfgNode {
+ class Expr extends Cfg::CfgNodes::ExprCfgNode {
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
}
@@ -406,9 +336,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
- predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
- none() // TODO
- }
+ predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) { none() }
/** Gets an immediate conditional successor of basic block `bb`, if any. */
SsaInput::BasicBlock getAConditionalBasicBlockSuccessor(SsaInput::BasicBlock bb, boolean branch) {
diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/TaintTrackingPrivate.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/TaintTrackingPrivate.qll
index 8cc0f0a87223..9c6132c7a291 100644
--- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/TaintTrackingPrivate.qll
+++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/TaintTrackingPrivate.qll
@@ -41,7 +41,7 @@ private module Cached {
)
or
// Flow through string interpolation
- exists(CfgNodes::ExprNodes::ExpandableStringCfgNode es |
+ exists(CfgNodes::ExprNodes::ExpandableStringExprCfgNode es |
nodeFrom.asExpr() = es.getAnExpr() and
nodeTo.asExpr() = es
)
diff --git a/powershell/ql/lib/semmle/code/powershell/frameworks/SystemManagementAutomationEngineIntrinsics/EngineIntrinsics.qll b/powershell/ql/lib/semmle/code/powershell/frameworks/SystemManagementAutomationEngineIntrinsics/EngineIntrinsics.qll
index 9f856f289495..b22dd618246a 100644
--- a/powershell/ql/lib/semmle/code/powershell/frameworks/SystemManagementAutomationEngineIntrinsics/EngineIntrinsics.qll
+++ b/powershell/ql/lib/semmle/code/powershell/frameworks/SystemManagementAutomationEngineIntrinsics/EngineIntrinsics.qll
@@ -6,7 +6,7 @@ module EngineIntrinsics {
private class EngineIntrinsicsGlobalEntry extends ModelInput::TypeModel {
override DataFlow::Node getASource(string type) {
type = "System.Management.Automation.EngineIntrinsics" and
- result.asExpr().getExpr().(VarReadAccess).getUserPath().toLowerCase() = "executioncontext"
+ result.asExpr().getExpr().(VarReadAccess).getVariable().getName().toLowerCase() = "executioncontext"
}
}
}
diff --git a/powershell/ql/lib/semmle/code/powershell/frameworks/data/ModelsAsData.qll b/powershell/ql/lib/semmle/code/powershell/frameworks/data/ModelsAsData.qll
index ddacb7b2d258..d18fdce39242 100644
--- a/powershell/ql/lib/semmle/code/powershell/frameworks/data/ModelsAsData.qll
+++ b/powershell/ql/lib/semmle/code/powershell/frameworks/data/ModelsAsData.qll
@@ -30,7 +30,7 @@ private class SummarizedCallableFromModel extends SummarizedCallable {
this = type + ";" + path
}
- override Call getACall() {
+ override CallExpr getACall() {
exists(API::MethodAccessNode base |
ModelOutput::resolvedSummaryBase(type, path, base) and
result = base.asCall().asExpr().getExpr()
diff --git a/powershell/ql/lib/semmle/code/powershell/frameworks/data/internal/ApiGraphModelsSpecific.qll b/powershell/ql/lib/semmle/code/powershell/frameworks/data/internal/ApiGraphModelsSpecific.qll
index 9bf974f325b1..c2061c238b25 100644
--- a/powershell/ql/lib/semmle/code/powershell/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/powershell/ql/lib/semmle/code/powershell/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -55,27 +55,6 @@ predicate hasImplicitTypeModel(string type, string otherType) {
parseType(otherType, type, _)
}
-pragma[nomagic]
-string getConstComponent(string consts, int n) {
- parseRelevantType(_, consts, _) and
- result = consts.splitAt(".", n)
-}
-
-private int getNumConstComponents(string consts) {
- result = strictcount(int n | exists(getConstComponent(consts, n)))
-}
-
-private DataFlow::TypePathNode getConstantFromConstPath(string consts, int n) {
- n = 1 and
- result.getComponent() = getConstComponent(consts, 0)
- or
- result = getConstantFromConstPath(consts, n - 1).getConstant(getConstComponent(consts, n - 1))
-}
-
-private DataFlow::TypePathNode getConstantFromConstPath(string consts) {
- result = getConstantFromConstPath(consts, getNumConstComponents(consts))
-}
-
/** Gets a Powershell-specific interpretation of the `(type, path)` tuple after resolving the first `n` access path tokens. */
bindingset[type, path]
API::Node getExtraNodeFromPath(string type, AccessPath path, int n) {
@@ -91,15 +70,8 @@ API::Node getExtraNodeFromPath(string type, AccessPath path, int n) {
/** Gets a Powershell-specific interpretation of the given `type`. */
API::Node getExtraNodeFromType(string type) {
- exists(string consts, string suffix, DataFlow::TypePathNode constRef |
- parseRelevantType(type, consts, suffix) and
- constRef = getConstantFromConstPath(consts)
- |
- suffix = "!" and
- result = constRef.track()
- or
- suffix = "" and
- result = constRef.track().getInstance()
+ exists(string consts, string suffix | parseRelevantType(type, consts, suffix) |
+ none() // TODO
)
or
type = "" and
@@ -187,7 +159,7 @@ predicate invocationMatchesExtraCallSiteFilter(InvokeNode invoke, AccessPathToke
/** An API graph node representing a method call. */
class InvokeNode extends API::MethodAccessNode {
/** Gets the number of arguments to the call. */
- int getNumArgument() { result = this.asCall().getNumberOfArguments() }
+ int getNumArgument() { result = count(this.asCall().getAnArgument()) }
}
/** Gets the `InvokeNode` corresponding to a specific invocation of `node`. */
diff --git a/powershell/ql/lib/semmle/code/powershell/internal/AstEscape.qll b/powershell/ql/lib/semmle/code/powershell/internal/AstEscape.qll
index 07148719f31f..7e031d537bdb 100644
--- a/powershell/ql/lib/semmle/code/powershell/internal/AstEscape.qll
+++ b/powershell/ql/lib/semmle/code/powershell/internal/AstEscape.qll
@@ -47,7 +47,7 @@ module Private {
final override Element getAChild() { result = super.getAStmt() }
}
- private class CmdExprElement extends ElementImpl instanceof PS::CmdExpr {
+ private class ExprStmtElement extends ElementImpl instanceof PS::ExprStmt {
final override T getANode() { result = interpret(super.getExpr()) }
final override Element getAChild() { none() }
@@ -78,18 +78,6 @@ module Private {
private class SwitchStmtElement extends ElementImpl instanceof PS::SwitchStmt {
final override Element getAChild() { result = super.getACase() }
}
-
- private class CmdBaseElement extends ElementImpl instanceof PS::CmdExpr {
- final override T getANode() { result = interpret(super.getExpr()) }
-
- final override Element getAChild() { none() }
- }
-
- private class CmdElement extends ElementImpl instanceof PS::Cmd {
- final override T getANode() { result = interpret(this) }
-
- final override Element getAChild() { none() }
- }
}
}
diff --git a/powershell/ql/lib/semmle/code/powershell/internal/Internal.qll b/powershell/ql/lib/semmle/code/powershell/internal/Internal.qll
deleted file mode 100644
index 853a9a247f52..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/internal/Internal.qll
+++ /dev/null
@@ -1,13 +0,0 @@
-module Private {
- import Parameter::Private
- import ExplicitWrite::Private
- import Argument::Private
- import Operation::Private
-}
-
-module Public {
- import Parameter::Public
- import ExplicitWrite::Public
- import Argument::Public
- import Operation::Public
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/internal/Operation.qll b/powershell/ql/lib/semmle/code/powershell/internal/Operation.qll
deleted file mode 100644
index a5e758d10b56..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/internal/Operation.qll
+++ /dev/null
@@ -1,31 +0,0 @@
-import powershell
-
-module Private {
- abstract private class AbstractOperation extends Expr {
- abstract Expr getAnOperand();
-
- abstract int getKind();
- }
-
- class BinaryOperation extends BinaryExpr, AbstractOperation {
- final override Expr getAnOperand() { result = BinaryExpr.super.getAnOperand() }
-
- final override int getKind() { result = BinaryExpr.super.getKind() }
- }
-
- class UnaryOperation extends UnaryExpr, AbstractOperation {
- final override Expr getAnOperand() { result = UnaryExpr.super.getOperand() }
-
- final override int getKind() { result = UnaryExpr.super.getKind() }
- }
-
- final class Operation = AbstractOperation;
-}
-
-module Public {
- class Operation = Private::Operation;
-
- class BinaryOperation = Private::BinaryOperation;
-
- class UnaryOperation = Private::UnaryOperation;
-}
diff --git a/powershell/ql/lib/semmle/code/powershell/internal/Parameter.qll b/powershell/ql/lib/semmle/code/powershell/internal/Parameter.qll
deleted file mode 100644
index 15f4136e22e9..000000000000
--- a/powershell/ql/lib/semmle/code/powershell/internal/Parameter.qll
+++ /dev/null
@@ -1,28 +0,0 @@
-import powershell
-
-module Private {
- class Parameter extends @parameter, Ast {
- override string toString() { result = this.getName().toString() }
-
- string getName() {
- exists(@variable_expression ve |
- parameter(this, ve, _, _) and
- variable_expression(ve, result, _, _, _, _, _, _, _, _, _, _)
- )
- }
-
- string getStaticType() { parameter(this, _, result, _) }
-
- int getNumAttributes() { parameter(this, _, _, result) }
-
- AttributeBase getAttribute(int i) { parameter_attribute(this, i, result) }
-
- AttributeBase getAnAttribute() { result = this.getAttribute(_) }
-
- Expr getDefaultValue() { parameter_default_value(this, result) }
-
- override SourceLocation getLocation() { parameter_location(this, result) }
- }
-}
-
-module Public { }
diff --git a/powershell/ql/lib/semmle/code/powershell/typetracking/internal/TypeTrackingImpl.qll b/powershell/ql/lib/semmle/code/powershell/typetracking/internal/TypeTrackingImpl.qll
index dcebe6117b54..36a605c25dc7 100644
--- a/powershell/ql/lib/semmle/code/powershell/typetracking/internal/TypeTrackingImpl.qll
+++ b/powershell/ql/lib/semmle/code/powershell/typetracking/internal/TypeTrackingImpl.qll
@@ -15,7 +15,8 @@ private import codeql.util.Unit
pragma[noinline]
private predicate sourceArgumentPositionMatch(
- CallCfgNode call, DataFlowPrivate::ArgumentNode arg, DataFlowDispatch::ParameterPosition ppos
+ ExprNodes::CallExprCfgNode call, DataFlowPrivate::ArgumentNode arg,
+ DataFlowDispatch::ParameterPosition ppos
) {
exists(DataFlowDispatch::ArgumentPosition apos |
arg.sourceArgumentOf(call, apos) and
@@ -213,7 +214,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
* Holds if `nodeFrom` steps to `nodeTo` by being returned from a call.
*/
predicate returnStep(Node nodeFrom, LocalSourceNode nodeTo) {
- exists(CallCfgNode call |
+ exists(ExprNodes::CallExprCfgNode call |
nodeFrom instanceof DataFlowPrivate::ReturnNode and
nodeFrom.(DataFlowPrivate::NodeImpl).getCfgScope() =
DataFlowDispatch::getTarget(DataFlowDispatch::TNormalCall(call)) and
diff --git a/powershell/ql/src/experimental/CommandInjection.ql b/powershell/ql/src/experimental/CommandInjection.ql
index 695c69a573e4..9f4696533ea9 100644
--- a/powershell/ql/src/experimental/CommandInjection.ql
+++ b/powershell/ql/src/experimental/CommandInjection.ql
@@ -11,7 +11,7 @@
import powershell
predicate containsScope(VarAccess outer, VarAccess inner) {
- outer.getUserPath() = inner.getUserPath() and
+ outer.getVariable().getName() = inner.getVariable().getName() and
outer != inner
}
@@ -23,16 +23,16 @@ predicate constantBinaryExpression(BinaryExpr binary) {
onlyConstantExpressions(binary.getLeft()) and onlyConstantExpressions(binary.getRight())
}
-predicate onlyConstantExpressions(Expr expr){
- expr instanceof StringConstExpr or constantBinaryExpression(expr) or constantTernaryExpression(expr)
+predicate onlyConstantExpressions(Expr expr) {
+ expr instanceof StringConstExpr or
+ constantBinaryExpression(expr) or
+ constantTernaryExpression(expr)
}
VarAccess getNonConstantVariableAssignment(VarAccess varexpr) {
- (
- exists(AssignStmt assignment |
- not onlyConstantExpressions(assignment.getRightHandSide().(CmdExpr).getExpr()) and
- result = assignment.getLeftHandSide()
- )
+ exists(AssignStmt assignment |
+ not onlyConstantExpressions(assignment.getRightHandSide()) and
+ result = assignment.getLeftHandSide()
) and
containsScope(result, varexpr)
}
@@ -44,31 +44,35 @@ VarAccess getParameterWithVariableScope(VarAccess varexpr) {
)
}
-Expr getAllSubExpressions(Expr expr)
-{
+Expr getAllSubExpressions(Expr expr) {
result = expr or
- result = getAllSubExpressions(expr.(ArrayLiteral).getAnElement()) or
- result = getAllSubExpressions(expr.(ArrayExpr).getStmtBlock().getAStmt().(Pipeline).getAComponent().(CmdExpr).getExpr())
+ result = getAllSubExpressions(expr.(ArrayLiteral).getAnExpr()) or
+ result =
+ getAllSubExpressions(expr.(ArrayExpr)
+ .getStmtBlock()
+ .getAStmt()
+ .(ExprStmt)
+ .getExpr()
+ .(Pipeline)
+ .getAComponent())
}
-Expr dangerousCommandElement(Cmd command)
-{
+Expr dangerousCommandElement(CallExpr command) {
(
- command.getKind() = 28 or
- command.getCommandName() = "Invoke-Expression"
+ command instanceof CallOperator or
+ command.getName() = "Invoke-Expression"
) and
result = getAllSubExpressions(command.getAnArgument())
}
from Expr commandarg, VarAccess unknownDeclaration
where
- exists(Cmd command |
+ exists(CallExpr command |
(
unknownDeclaration = getNonConstantVariableAssignment(commandarg) or
unknownDeclaration = getParameterWithVariableScope(commandarg)
- )
- and
+ ) and
commandarg = dangerousCommandElement(command)
)
select commandarg.(VarAccess).getLocation(), "Unsafe flow to command argument from $@.",
- unknownDeclaration, unknownDeclaration.getUserPath()
+ unknownDeclaration, unknownDeclaration.getVariable().getName()
diff --git a/powershell/ql/test/TestUtilities/InlineFlowTestUtil.qll b/powershell/ql/test/TestUtilities/InlineFlowTestUtil.qll
index 0712a6500344..96fe15ea7a96 100644
--- a/powershell/ql/test/TestUtilities/InlineFlowTestUtil.qll
+++ b/powershell/ql/test/TestUtilities/InlineFlowTestUtil.qll
@@ -6,19 +6,19 @@ import powershell
import semmle.code.powershell.dataflow.DataFlow
predicate defaultSource(DataFlow::Node src) {
- src.asStmt().getStmt().(Cmd).getCommandName() = ["Source", "Taint"]
+ src.asExpr().getExpr().(CmdCall).getName() = ["Source", "Taint"]
or
src.asParameter().getName().matches(["Source%", "Taint%"])
}
predicate defaultSink(DataFlow::Node sink) {
- exists(Cmd cmd | cmd.getCommandName() = "Sink" | sink.asExpr().getExpr() = cmd.getAnArgument())
+ exists(CmdCall cmd | cmd.getName() = "Sink" | sink.asExpr().getExpr() = cmd.getAnArgument())
}
string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and
(
- src.asStmt().getStmt().(Cmd).getAnArgument().(StringConstExpr).getValue().getValue() = result
+ src.asExpr().getExpr().(CmdCall).getAnArgument().(StringConstExpr).getValue().getValue() = result
or
src.asParameter().getName().regexpCapture(["Source(.+)", "Taint(.+)"], 1) = result
)
diff --git a/powershell/ql/test/library-tests/ast/Arrays/arrays.expected b/powershell/ql/test/library-tests/ast/Arrays/arrays.expected
index 1c50d2710a1b..9830fe986bd6 100644
--- a/powershell/ql/test/library-tests/ast/Arrays/arrays.expected
+++ b/powershell/ql/test/library-tests/ast/Arrays/arrays.expected
@@ -1,23 +1,23 @@
arrayExpr
-| Arrays.ps1:11:11:11:25 | @(...) | Arrays.ps1:11:13:11:24 | {...} |
-| Arrays.ps1:14:41:14:44 | @(...) | Arrays.ps1:0:0:0:0 | {...} |
+| Arrays.ps1:11:11:11:24 | @(...) | Arrays.ps1:11:13:11:23 | {...} |
+| Arrays.ps1:14:41:14:43 | @(...) | Arrays.ps1:0:0:0:-1 | {...} |
arrayLiteral
-| Arrays.ps1:1:11:1:37 | ...,... | 0 | Arrays.ps1:1:11:1:12 | 1 |
-| Arrays.ps1:1:11:1:37 | ...,... | 1 | Arrays.ps1:1:13:1:14 | 2 |
-| Arrays.ps1:1:11:1:37 | ...,... | 2 | Arrays.ps1:1:15:1:18 | a |
-| Arrays.ps1:1:11:1:37 | ...,... | 3 | Arrays.ps1:1:19:1:24 | true |
-| Arrays.ps1:1:11:1:37 | ...,... | 4 | Arrays.ps1:1:25:1:31 | false |
-| Arrays.ps1:1:11:1:37 | ...,... | 5 | Arrays.ps1:1:32:1:37 | null |
-| Arrays.ps1:5:34:5:37 | ...,... | 0 | Arrays.ps1:5:34:5:35 | 2 |
-| Arrays.ps1:5:34:5:37 | ...,... | 1 | Arrays.ps1:5:36:5:37 | 2 |
-| Arrays.ps1:6:9:6:12 | ...,... | 0 | Arrays.ps1:6:9:6:10 | 0 |
-| Arrays.ps1:6:9:6:12 | ...,... | 1 | Arrays.ps1:6:11:6:12 | 0 |
-| Arrays.ps1:7:9:7:12 | ...,... | 0 | Arrays.ps1:7:9:7:10 | 1 |
-| Arrays.ps1:7:9:7:12 | ...,... | 1 | Arrays.ps1:7:11:7:12 | 0 |
-| Arrays.ps1:8:9:8:12 | ...,... | 0 | Arrays.ps1:8:9:8:10 | 0 |
-| Arrays.ps1:8:9:8:12 | ...,... | 1 | Arrays.ps1:8:11:8:12 | 1 |
-| Arrays.ps1:9:9:9:12 | ...,... | 0 | Arrays.ps1:9:9:9:10 | 1 |
-| Arrays.ps1:9:9:9:12 | ...,... | 1 | Arrays.ps1:9:11:9:12 | 1 |
-| Arrays.ps1:11:13:11:24 | ...,... | 0 | Arrays.ps1:11:13:11:16 | a |
-| Arrays.ps1:11:13:11:24 | ...,... | 1 | Arrays.ps1:11:17:11:20 | b |
-| Arrays.ps1:11:13:11:24 | ...,... | 2 | Arrays.ps1:11:21:11:24 | c |
+| Arrays.ps1:1:11:1:36 | ...,... | 0 | Arrays.ps1:1:11:1:11 | 1 |
+| Arrays.ps1:1:11:1:36 | ...,... | 1 | Arrays.ps1:1:13:1:13 | 2 |
+| Arrays.ps1:1:11:1:36 | ...,... | 2 | Arrays.ps1:1:15:1:17 | a |
+| Arrays.ps1:1:11:1:36 | ...,... | 3 | Arrays.ps1:1:19:1:23 | true |
+| Arrays.ps1:1:11:1:36 | ...,... | 4 | Arrays.ps1:1:25:1:30 | false |
+| Arrays.ps1:1:11:1:36 | ...,... | 5 | Arrays.ps1:1:32:1:36 | null |
+| Arrays.ps1:5:34:5:36 | ...,... | 0 | Arrays.ps1:5:34:5:34 | 2 |
+| Arrays.ps1:5:34:5:36 | ...,... | 1 | Arrays.ps1:5:36:5:36 | 2 |
+| Arrays.ps1:6:9:6:11 | ...,... | 0 | Arrays.ps1:6:9:6:9 | 0 |
+| Arrays.ps1:6:9:6:11 | ...,... | 1 | Arrays.ps1:6:11:6:11 | 0 |
+| Arrays.ps1:7:9:7:11 | ...,... | 0 | Arrays.ps1:7:9:7:9 | 1 |
+| Arrays.ps1:7:9:7:11 | ...,... | 1 | Arrays.ps1:7:11:7:11 | 0 |
+| Arrays.ps1:8:9:8:11 | ...,... | 0 | Arrays.ps1:8:9:8:9 | 0 |
+| Arrays.ps1:8:9:8:11 | ...,... | 1 | Arrays.ps1:8:11:8:11 | 1 |
+| Arrays.ps1:9:9:9:11 | ...,... | 0 | Arrays.ps1:9:9:9:9 | 1 |
+| Arrays.ps1:9:9:9:11 | ...,... | 1 | Arrays.ps1:9:11:9:11 | 1 |
+| Arrays.ps1:11:13:11:23 | ...,... | 0 | Arrays.ps1:11:13:11:15 | a |
+| Arrays.ps1:11:13:11:23 | ...,... | 1 | Arrays.ps1:11:17:11:19 | b |
+| Arrays.ps1:11:13:11:23 | ...,... | 2 | Arrays.ps1:11:21:11:23 | c |
diff --git a/powershell/ql/test/library-tests/ast/Arrays/arrays.ql b/powershell/ql/test/library-tests/ast/Arrays/arrays.ql
index 087ee78e4ef9..3eaaa38503f5 100644
--- a/powershell/ql/test/library-tests/ast/Arrays/arrays.ql
+++ b/powershell/ql/test/library-tests/ast/Arrays/arrays.ql
@@ -3,5 +3,5 @@ import powershell
query predicate arrayExpr(ArrayExpr arrayExpr, StmtBlock subExpr) { subExpr = arrayExpr.getStmtBlock() }
query predicate arrayLiteral(ArrayLiteral arrayLiteral, int i, Expr e) {
- e = arrayLiteral.getElement(i)
+ e = arrayLiteral.getExpr(i)
}
diff --git a/powershell/ql/test/library-tests/ast/Blocks/blocks.expected b/powershell/ql/test/library-tests/ast/Blocks/blocks.expected
index 1d23ed850efe..0d4882c4c417 100644
--- a/powershell/ql/test/library-tests/ast/Blocks/blocks.expected
+++ b/powershell/ql/test/library-tests/ast/Blocks/blocks.expected
@@ -1 +1,2 @@
-| ParamBlock.ps1:2:1:5:2 | param(...) | 0 | ParamBlock.ps1:3:5:4:23 | Parameter |
+| ParamBlock.ps1:1:1:5:1 | {...} | 0 | ParamBlock.ps1:1:1:5:1 | Parameter |
+| ParamBlock.ps1:1:1:5:1 | {...} | 1 | ParamBlock.ps1:1:1:5:1 | [synth] pipeline |
diff --git a/powershell/ql/test/library-tests/ast/Blocks/blocks.ql b/powershell/ql/test/library-tests/ast/Blocks/blocks.ql
index 9c4288d35601..6140e96a2058 100644
--- a/powershell/ql/test/library-tests/ast/Blocks/blocks.ql
+++ b/powershell/ql/test/library-tests/ast/Blocks/blocks.ql
@@ -1,5 +1,5 @@
import powershell
-query predicate paramBlockHasParam(ParamBlock block, int i, Parameter p) {
+query predicate paramBlockHasParam(ScriptBlock block, int i, Parameter p) {
p = block.getParameter(i)
}
\ No newline at end of file
diff --git a/powershell/ql/test/library-tests/ast/Expressions/expressions.expected b/powershell/ql/test/library-tests/ast/Expressions/expressions.expected
index 30aabf5cb277..7deaa7795dd4 100644
--- a/powershell/ql/test/library-tests/ast/Expressions/expressions.expected
+++ b/powershell/ql/test/library-tests/ast/Expressions/expressions.expected
@@ -1,19 +1,15 @@
binaryExpr
-| BinaryExpression.ps1:3:11:3:24 | ...+... | BinaryExpression.ps1:3:11:3:16 | val1 | BinaryExpression.ps1:3:19:3:24 | val2 |
-| TernaryExpression.ps1:1:9:1:16 | ... -gt ... | TernaryExpression.ps1:1:9:1:10 | 6 | TernaryExpression.ps1:1:15:1:16 | 7 |
+| BinaryExpression.ps1:3:11:3:23 | ...+... | BinaryExpression.ps1:3:11:3:15 | val1 | BinaryExpression.ps1:3:19:3:23 | val2 |
+| TernaryExpression.ps1:1:9:1:15 | ... -gt ... | TernaryExpression.ps1:1:9:1:9 | 6 | TernaryExpression.ps1:1:15:1:15 | 7 |
cmdExpr
-| BinaryExpression.ps1:1:9:1:10 | 1 | BinaryExpression.ps1:1:9:1:10 | 1 |
-| BinaryExpression.ps1:2:9:2:10 | 2 | BinaryExpression.ps1:2:9:2:10 | 2 |
-| BinaryExpression.ps1:3:11:3:24 | ...+... | BinaryExpression.ps1:3:11:3:24 | ...+... |
-| BinaryExpression.ps1:4:1:4:8 | result | BinaryExpression.ps1:4:1:4:8 | result |
-| ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name | ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name |
-| ExpandableString.ps1:1:23:1:38 | Now | ExpandableString.ps1:1:23:1:38 | Now |
-| SubExpression.ps1:1:1:1:24 | call to AddDays | SubExpression.ps1:1:1:1:24 | call to AddDays |
-| SubExpression.ps1:2:1:2:22 | call to AddDays | SubExpression.ps1:2:1:2:22 | call to AddDays |
-| TernaryExpression.ps1:1:8:1:23 | ...?...:... | TernaryExpression.ps1:1:8:1:23 | ...?...:... |
-| TernaryExpression.ps1:1:9:1:16 | ... -gt ... | TernaryExpression.ps1:1:9:1:16 | ... -gt ... |
+| BinaryExpression.ps1:4:1:4:7 | [Stmt] result | BinaryExpression.ps1:4:1:4:7 | result |
+| ExpandableString.ps1:1:1:1:39 | [Stmt] Date: $([DateTime]::Now)\nName: $name | ExpandableString.ps1:1:1:1:39 | Date: $([DateTime]::Now)\nName: $name |
+| ExpandableString.ps1:1:23:1:37 | [Stmt] Now | ExpandableString.ps1:1:23:1:37 | Now |
+| SubExpression.ps1:1:1:1:23 | [Stmt] Call to AddDays | SubExpression.ps1:1:1:1:23 | Call to AddDays |
+| SubExpression.ps1:1:3:1:10 | [Stmt] Call to Get-Date | SubExpression.ps1:1:3:1:10 | Call to Get-Date |
+| SubExpression.ps1:2:1:2:21 | [Stmt] Call to AddDays | SubExpression.ps1:2:1:2:21 | Call to AddDays |
+| SubExpression.ps1:2:3:2:10 | [Stmt] Call to Get-Date | SubExpression.ps1:2:3:2:10 | Call to Get-Date |
invokeMemoryExpression
-| SubExpression.ps1:1:1:1:24 | call to AddDays | SubExpression.ps1:1:1:1:12 | $(...) | 0 | SubExpression.ps1:1:21:1:23 | 10 |
+| SubExpression.ps1:1:1:1:23 | Call to AddDays | SubExpression.ps1:1:1:1:11 | $(...) | 0 | SubExpression.ps1:1:21:1:22 | 10 |
expandableString
-| ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name | 0 | ExpandableString.ps1:1:8:1:13 | name |
-| ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name | 1 | ExpandableString.ps1:1:21:1:39 | $(...) |
+| ExpandableString.ps1:1:1:1:39 | Date: $([DateTime]::Now)\nName: $name | 1 | ExpandableString.ps1:1:21:1:38 | $(...) |
diff --git a/powershell/ql/test/library-tests/ast/Expressions/expressions.ql b/powershell/ql/test/library-tests/ast/Expressions/expressions.ql
index 6f3064f5c40c..2583cdef4b81 100644
--- a/powershell/ql/test/library-tests/ast/Expressions/expressions.ql
+++ b/powershell/ql/test/library-tests/ast/Expressions/expressions.ql
@@ -5,8 +5,8 @@ query predicate binaryExpr(BinaryExpr e, Expr e1, Expr e2) {
e2 = e.getRight()
}
-query predicate cmdExpr(CmdExpr cmd, Expr e) {
- e = cmd.getExpr()
+query predicate cmdExpr(ExprStmt exprStmt, Expr e) {
+ e = exprStmt.getExpr()
}
query predicate invokeMemoryExpression(InvokeMemberExpr invoke, Expr e, int i, Expr arg) {
diff --git a/powershell/ql/test/library-tests/ast/Loops/loops.expected b/powershell/ql/test/library-tests/ast/Loops/loops.expected
index 503d8894a46a..0015ed68b0d0 100644
--- a/powershell/ql/test/library-tests/ast/Loops/loops.expected
+++ b/powershell/ql/test/library-tests/ast/Loops/loops.expected
@@ -1,6 +1,6 @@
doUntil
-| DoUntil.ps1:1:1:7:19 | DoUntil | DoUntil.ps1:7:10:7:18 | ... -le ... | DoUntil.ps1:2:1:7:2 | {...} |
+| DoUntil.ps1:1:1:7:18 | do...until... | DoUntil.ps1:7:10:7:17 | ... -le ... | DoUntil.ps1:2:1:7:1 | {...} |
doWhile
-| DoWhile.ps1:1:1:7:19 | DoWhile | DoWhile.ps1:7:10:7:18 | ... -le ... | DoWhile.ps1:2:1:7:2 | {...} |
+| DoWhile.ps1:1:1:7:18 | do...while... | DoWhile.ps1:7:10:7:17 | ... -le ... | DoWhile.ps1:2:1:7:1 | {...} |
while
-| While.ps1:2:1:13:2 | while(...) {...} | While.ps1:2:8:2:18 | ... -le ... | While.ps1:3:1:13:2 | {...} |
+| While.ps1:2:1:13:1 | while(...) {...} | While.ps1:2:8:2:17 | ... -le ... | While.ps1:3:1:13:1 | {...} |
diff --git a/powershell/ql/test/library-tests/ast/Loops/loops.ql b/powershell/ql/test/library-tests/ast/Loops/loops.ql
index 55c750da7cb6..1a4e3d678110 100644
--- a/powershell/ql/test/library-tests/ast/Loops/loops.ql
+++ b/powershell/ql/test/library-tests/ast/Loops/loops.ql
@@ -1,16 +1,16 @@
import powershell
-query predicate doUntil(DoUntilStmt s, PipelineBase e, StmtBlock body) {
+query predicate doUntil(DoUntilStmt s, Expr e, StmtBlock body) {
e = s.getCondition() and
body = s.getBody()
}
-query predicate doWhile(DoWhileStmt s, PipelineBase e, StmtBlock body) {
+query predicate doWhile(DoWhileStmt s, Expr e, StmtBlock body) {
e = s.getCondition() and
body = s.getBody()
}
-query predicate while(WhileStmt s, PipelineBase e, StmtBlock body) {
+query predicate while(WhileStmt s, Expr e, StmtBlock body) {
e = s.getCondition() and
body = s.getBody()
}
diff --git a/powershell/ql/test/library-tests/ast/Redirections/redirections.expected b/powershell/ql/test/library-tests/ast/Redirections/redirections.expected
index 968fcee62ee2..c48b8b8df703 100644
--- a/powershell/ql/test/library-tests/ast/Redirections/redirections.expected
+++ b/powershell/ql/test/library-tests/ast/Redirections/redirections.expected
@@ -1,2 +1,2 @@
-| FileRedirection.ps1:3:3:3:7 | MergingRedirection |
-| FileRedirection.ps1:3:8:3:20 | FileRedirection |
+| FileRedirection.ps1:3:3:3:6 | MergingRedirection |
+| FileRedirection.ps1:3:8:3:19 | FileRedirection |
diff --git a/powershell/ql/test/library-tests/ast/Statements/statements.expected b/powershell/ql/test/library-tests/ast/Statements/statements.expected
index 52cf8de5795b..f8994f476941 100644
--- a/powershell/ql/test/library-tests/ast/Statements/statements.expected
+++ b/powershell/ql/test/library-tests/ast/Statements/statements.expected
@@ -1,24 +1,25 @@
-| ExitStatement.ps1:1:1:1:8 | exit ... |
-| ExitStatement.ps1:1:6:1:8 | -1 |
-| IfStatement.ps1:1:1:1:7 | ...=... |
-| IfStatement.ps1:1:6:1:7 | 4 |
-| IfStatement.ps1:3:1:8:2 | if (...) {...} else {...} |
-| IfStatement.ps1:3:5:3:13 | ... -ge ... |
-| IfStatement.ps1:4:2:4:36 | $x is greater than or equal to 3 |
-| IfStatement.ps1:7:2:7:21 | $x is less than 3 |
-| TrapStatement.ps1:1:1:4:2 | TrapTest |
-| TrapStatement.ps1:2:5:2:26 | TrapStatement at: TrapStatement.ps1:2:5:2:26 |
-| TrapStatement.ps1:2:11:2:25 | Error found. |
-| TrapStatement.ps1:3:5:3:19 | call to nonsenseString |
-| TrapStatement.ps1:6:1:6:9 | call to TrapTest |
-| Try.ps1:1:1:13:2 | try {...} |
-| Try.ps1:2:4:2:95 | ...=... |
-| Try.ps1:2:17:2:95 | call to New-Object |
-| Try.ps1:2:69:2:94 | ...,... |
-| Try.ps1:3:5:3:21 | throw ... |
-| Try.ps1:3:11:3:21 | Exception |
-| Try.ps1:6:5:6:64 | Unable to download MyDoc.doc from http://www.contoso.com. |
-| Try.ps1:9:5:9:52 | An error occurred that could not be resolved. |
-| Try.ps1:12:5:12:37 | The finally block is executed. |
-| UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | Get-Number |
-| UseProcessBlockForPipelineCommand.ps1:10:5:10:12 | Number |
+| ExitStatement.ps1:1:1:1:7 | exit ... |
+| IfStatement.ps1:1:1:1:6 | ...=... |
+| IfStatement.ps1:3:1:8:1 | [Stmt] if (...) {...} else {...} |
+| IfStatement.ps1:3:15:5:1 | {...} |
+| IfStatement.ps1:4:2:4:35 | [Stmt] $x is greater than or equal to 3 |
+| IfStatement.ps1:6:6:8:1 | {...} |
+| IfStatement.ps1:7:2:7:20 | [Stmt] $x is less than 3 |
+| TrapStatement.ps1:1:1:4:1 | def of TrapTest |
+| TrapStatement.ps1:2:5:2:25 | trap {...} |
+| TrapStatement.ps1:2:10:2:25 | {...} |
+| TrapStatement.ps1:2:11:2:24 | [Stmt] Error found. |
+| TrapStatement.ps1:3:5:3:18 | [Stmt] Call to nonsenseString |
+| TrapStatement.ps1:6:1:6:8 | [Stmt] Call to TrapTest |
+| Try.ps1:1:1:13:1 | try {...} |
+| Try.ps1:1:5:4:1 | {...} |
+| Try.ps1:2:4:2:94 | ...=... |
+| Try.ps1:3:5:3:20 | throw ... |
+| Try.ps1:5:57:7:1 | {...} |
+| Try.ps1:6:5:6:63 | [Stmt] Unable to download MyDoc.doc from http://www.contoso.com. |
+| Try.ps1:8:7:10:1 | {...} |
+| Try.ps1:9:5:9:51 | [Stmt] An error occurred that could not be resolved. |
+| Try.ps1:11:9:13:1 | {...} |
+| Try.ps1:12:5:12:36 | [Stmt] The finally block is executed. |
+| UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | def of Get-Number |
+| UseProcessBlockForPipelineCommand.ps1:10:5:10:11 | [Stmt] Number |
diff --git a/powershell/ql/test/library-tests/ast/parent.expected b/powershell/ql/test/library-tests/ast/parent.expected
index 61bba880ae0a..13a4da5ff1c0 100644
--- a/powershell/ql/test/library-tests/ast/parent.expected
+++ b/powershell/ql/test/library-tests/ast/parent.expected
@@ -1,385 +1,388 @@
-| Arrays/Arrays.ps1:0:0:0:0 | {...} | Arrays/Arrays.ps1:14:41:14:44 | @(...) |
-| Arrays/Arrays.ps1:1:1:1:8 | array1 | Arrays/Arrays.ps1:1:1:1:37 | ...=... |
-| Arrays/Arrays.ps1:1:1:1:37 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:1:1:15:15 | {...} | Arrays/Arrays.ps1:1:1:15:15 | Arrays.ps1 |
-| Arrays/Arrays.ps1:1:11:1:12 | 1 | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:11:1:37 | ...,... | Arrays/Arrays.ps1:1:1:1:37 | ...=... |
-| Arrays/Arrays.ps1:1:11:1:37 | ...,... | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:13:1:14 | 2 | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:15:1:18 | a | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:19:1:24 | true | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:25:1:31 | false | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:1:32:1:37 | null | Arrays/Arrays.ps1:1:11:1:37 | ...,... |
-| Arrays/Arrays.ps1:2:1:2:8 | array1 | Arrays/Arrays.ps1:2:1:2:11 | ...[...] |
-| Arrays/Arrays.ps1:2:1:2:11 | ...[...] | Arrays/Arrays.ps1:2:1:2:15 | ...=... |
-| Arrays/Arrays.ps1:2:1:2:15 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:2:9:2:10 | 1 | Arrays/Arrays.ps1:2:1:2:11 | ...[...] |
-| Arrays/Arrays.ps1:2:14:2:15 | 3 | Arrays/Arrays.ps1:2:1:2:15 | ...=... |
-| Arrays/Arrays.ps1:2:14:2:15 | 3 | Arrays/Arrays.ps1:2:14:2:15 | 3 |
-| Arrays/Arrays.ps1:3:1:3:8 | array1 | Arrays/Arrays.ps1:3:1:3:11 | ...[...] |
-| Arrays/Arrays.ps1:3:1:3:11 | ...[...] | Arrays/Arrays.ps1:3:1:3:17 | ...=... |
-| Arrays/Arrays.ps1:3:1:3:17 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:3:9:3:10 | 2 | Arrays/Arrays.ps1:3:1:3:11 | ...[...] |
-| Arrays/Arrays.ps1:3:14:3:17 | b | Arrays/Arrays.ps1:3:1:3:17 | ...=... |
-| Arrays/Arrays.ps1:3:14:3:17 | b | Arrays/Arrays.ps1:3:14:3:17 | b |
-| Arrays/Arrays.ps1:5:1:5:8 | array2 | Arrays/Arrays.ps1:5:1:5:37 | ...=... |
-| Arrays/Arrays.ps1:5:1:5:37 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:5:11:5:21 | New-Object | Arrays/Arrays.ps1:5:11:5:37 | call to New-Object |
-| Arrays/Arrays.ps1:5:11:5:37 | call to New-Object | Arrays/Arrays.ps1:5:1:5:37 | ...=... |
-| Arrays/Arrays.ps1:5:22:5:33 | object[,] | Arrays/Arrays.ps1:5:11:5:37 | call to New-Object |
-| Arrays/Arrays.ps1:5:34:5:35 | 2 | Arrays/Arrays.ps1:5:34:5:37 | ...,... |
-| Arrays/Arrays.ps1:5:34:5:37 | ...,... | Arrays/Arrays.ps1:5:11:5:37 | call to New-Object |
-| Arrays/Arrays.ps1:5:36:5:37 | 2 | Arrays/Arrays.ps1:5:34:5:37 | ...,... |
-| Arrays/Arrays.ps1:6:1:6:8 | array2 | Arrays/Arrays.ps1:6:1:6:13 | ...[...] |
-| Arrays/Arrays.ps1:6:1:6:13 | ...[...] | Arrays/Arrays.ps1:6:1:6:22 | ...=... |
-| Arrays/Arrays.ps1:6:1:6:22 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:6:9:6:10 | 0 | Arrays/Arrays.ps1:6:9:6:12 | ...,... |
-| Arrays/Arrays.ps1:6:9:6:12 | ...,... | Arrays/Arrays.ps1:6:1:6:13 | ...[...] |
-| Arrays/Arrays.ps1:6:11:6:12 | 0 | Arrays/Arrays.ps1:6:9:6:12 | ...,... |
-| Arrays/Arrays.ps1:6:16:6:22 | key1 | Arrays/Arrays.ps1:6:1:6:22 | ...=... |
-| Arrays/Arrays.ps1:6:16:6:22 | key1 | Arrays/Arrays.ps1:6:16:6:22 | key1 |
-| Arrays/Arrays.ps1:7:1:7:8 | array2 | Arrays/Arrays.ps1:7:1:7:13 | ...[...] |
-| Arrays/Arrays.ps1:7:1:7:13 | ...[...] | Arrays/Arrays.ps1:7:1:7:22 | ...=... |
-| Arrays/Arrays.ps1:7:1:7:22 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:7:9:7:10 | 1 | Arrays/Arrays.ps1:7:9:7:12 | ...,... |
-| Arrays/Arrays.ps1:7:9:7:12 | ...,... | Arrays/Arrays.ps1:7:1:7:13 | ...[...] |
-| Arrays/Arrays.ps1:7:11:7:12 | 0 | Arrays/Arrays.ps1:7:9:7:12 | ...,... |
-| Arrays/Arrays.ps1:7:16:7:22 | key1 | Arrays/Arrays.ps1:7:1:7:22 | ...=... |
-| Arrays/Arrays.ps1:7:16:7:22 | key1 | Arrays/Arrays.ps1:7:16:7:22 | key1 |
-| Arrays/Arrays.ps1:8:1:8:8 | array2 | Arrays/Arrays.ps1:8:1:8:13 | ...[...] |
-| Arrays/Arrays.ps1:8:1:8:13 | ...[...] | Arrays/Arrays.ps1:8:1:8:24 | ...=... |
-| Arrays/Arrays.ps1:8:1:8:24 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:8:9:8:10 | 0 | Arrays/Arrays.ps1:8:9:8:12 | ...,... |
-| Arrays/Arrays.ps1:8:9:8:12 | ...,... | Arrays/Arrays.ps1:8:1:8:13 | ...[...] |
-| Arrays/Arrays.ps1:8:11:8:12 | 1 | Arrays/Arrays.ps1:8:9:8:12 | ...,... |
-| Arrays/Arrays.ps1:8:16:8:24 | value1 | Arrays/Arrays.ps1:8:1:8:24 | ...=... |
-| Arrays/Arrays.ps1:8:16:8:24 | value1 | Arrays/Arrays.ps1:8:16:8:24 | value1 |
-| Arrays/Arrays.ps1:9:1:9:8 | array2 | Arrays/Arrays.ps1:9:1:9:13 | ...[...] |
-| Arrays/Arrays.ps1:9:1:9:13 | ...[...] | Arrays/Arrays.ps1:9:1:9:21 | ...=... |
-| Arrays/Arrays.ps1:9:1:9:21 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:9:9:9:10 | 1 | Arrays/Arrays.ps1:9:9:9:12 | ...,... |
-| Arrays/Arrays.ps1:9:9:9:12 | ...,... | Arrays/Arrays.ps1:9:1:9:13 | ...[...] |
-| Arrays/Arrays.ps1:9:11:9:12 | 1 | Arrays/Arrays.ps1:9:9:9:12 | ...,... |
-| Arrays/Arrays.ps1:9:16:9:21 | null | Arrays/Arrays.ps1:9:1:9:21 | ...=... |
-| Arrays/Arrays.ps1:9:16:9:21 | null | Arrays/Arrays.ps1:9:16:9:21 | null |
-| Arrays/Arrays.ps1:11:1:11:8 | array3 | Arrays/Arrays.ps1:11:1:11:25 | ...=... |
-| Arrays/Arrays.ps1:11:1:11:25 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:11:11:11:25 | @(...) | Arrays/Arrays.ps1:11:1:11:25 | ...=... |
-| Arrays/Arrays.ps1:11:11:11:25 | @(...) | Arrays/Arrays.ps1:11:11:11:25 | @(...) |
-| Arrays/Arrays.ps1:11:13:11:16 | a | Arrays/Arrays.ps1:11:13:11:24 | ...,... |
-| Arrays/Arrays.ps1:11:13:11:24 | ...,... | Arrays/Arrays.ps1:11:13:11:24 | ...,... |
-| Arrays/Arrays.ps1:11:13:11:24 | ...,... | Arrays/Arrays.ps1:11:13:11:24 | {...} |
-| Arrays/Arrays.ps1:11:13:11:24 | {...} | Arrays/Arrays.ps1:11:11:11:25 | @(...) |
-| Arrays/Arrays.ps1:11:17:11:20 | b | Arrays/Arrays.ps1:11:13:11:24 | ...,... |
-| Arrays/Arrays.ps1:11:21:11:24 | c | Arrays/Arrays.ps1:11:13:11:24 | ...,... |
-| Arrays/Arrays.ps1:12:1:12:8 | array3 | Arrays/Arrays.ps1:12:1:12:14 | count |
-| Arrays/Arrays.ps1:12:1:12:14 | count | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:12:1:12:14 | count | Arrays/Arrays.ps1:12:1:12:14 | count |
-| Arrays/Arrays.ps1:12:9:12:14 | count | Arrays/Arrays.ps1:12:1:12:14 | count |
-| Arrays/Arrays.ps1:14:1:14:8 | array4 | Arrays/Arrays.ps1:14:1:14:44 | ...=... |
-| Arrays/Arrays.ps1:14:1:14:44 | ...=... | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:14:11:14:41 | System.Collections.ArrayList | Arrays/Arrays.ps1:14:11:14:44 | [...]... |
-| Arrays/Arrays.ps1:14:11:14:44 | [...]... | Arrays/Arrays.ps1:14:1:14:44 | ...=... |
-| Arrays/Arrays.ps1:14:11:14:44 | [...]... | Arrays/Arrays.ps1:14:11:14:44 | [...]... |
-| Arrays/Arrays.ps1:14:41:14:44 | @(...) | Arrays/Arrays.ps1:14:11:14:44 | [...]... |
-| Arrays/Arrays.ps1:15:1:15:8 | array4 | Arrays/Arrays.ps1:15:1:15:15 | call to Add |
-| Arrays/Arrays.ps1:15:1:15:15 | call to Add | Arrays/Arrays.ps1:1:1:15:15 | {...} |
-| Arrays/Arrays.ps1:15:1:15:15 | call to Add | Arrays/Arrays.ps1:15:1:15:15 | call to Add |
-| Arrays/Arrays.ps1:15:9:15:12 | Add | Arrays/Arrays.ps1:15:1:15:15 | call to Add |
-| Arrays/Arrays.ps1:15:13:15:14 | 1 | Arrays/Arrays.ps1:15:1:15:15 | call to Add |
-| Blocks/ParamBlock.ps1:1:1:1:18 | CmdletBinding | Blocks/ParamBlock.ps1:2:1:5:2 | param(...) |
-| Blocks/ParamBlock.ps1:2:1:5:2 | param(...) | Blocks/ParamBlock.ps1:1:1:5:2 | ParamBlock.ps1 |
-| Blocks/ParamBlock.ps1:2:1:5:2 | {...} | Blocks/ParamBlock.ps1:1:1:5:2 | ParamBlock.ps1 |
-| Blocks/ParamBlock.ps1:3:5:3:18 | Parameter | Blocks/ParamBlock.ps1:3:5:4:23 | Parameter |
-| Blocks/ParamBlock.ps1:3:5:4:23 | Parameter | Blocks/ParamBlock.ps1:2:1:5:2 | param(...) |
-| Blocks/ParamBlock.ps1:4:5:4:13 | string | Blocks/ParamBlock.ps1:3:5:4:23 | Parameter |
-| Dynamic/DynamicExecution.ps1:1:1:1:5 | foo | Dynamic/DynamicExecution.ps1:1:1:1:17 | ...=... |
-| Dynamic/DynamicExecution.ps1:1:1:1:17 | ...=... | Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} |
-| Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} | Dynamic/DynamicExecution.ps1:1:1:5:8 | DynamicExecution.ps1 |
-| Dynamic/DynamicExecution.ps1:1:8:1:17 | cmd.exe | Dynamic/DynamicExecution.ps1:1:1:1:17 | ...=... |
-| Dynamic/DynamicExecution.ps1:1:8:1:17 | cmd.exe | Dynamic/DynamicExecution.ps1:1:8:1:17 | cmd.exe |
-| Dynamic/DynamicExecution.ps1:2:1:2:18 | Invoke-Expression | Dynamic/DynamicExecution.ps1:2:1:2:23 | call to Invoke-Expression |
-| Dynamic/DynamicExecution.ps1:2:1:2:23 | call to Invoke-Expression | Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} |
-| Dynamic/DynamicExecution.ps1:2:19:2:23 | foo | Dynamic/DynamicExecution.ps1:2:1:2:23 | call to Invoke-Expression |
-| Dynamic/DynamicExecution.ps1:3:1:3:14 | scriptblock | Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create |
-| Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create | Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} |
-| Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create | Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create |
-| Dynamic/DynamicExecution.ps1:3:16:3:22 | Create | Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create |
-| Dynamic/DynamicExecution.ps1:3:23:3:27 | foo | Dynamic/DynamicExecution.ps1:3:1:3:28 | call to Create |
-| Dynamic/DynamicExecution.ps1:4:1:4:32 | call | Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} |
-| Dynamic/DynamicExecution.ps1:4:3:4:32 | (...) | Dynamic/DynamicExecution.ps1:4:1:4:32 | call |
-| Dynamic/DynamicExecution.ps1:4:4:4:17 | scriptblock | Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create |
-| Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create | Dynamic/DynamicExecution.ps1:4:3:4:32 | (...) |
-| Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create | Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create |
-| Dynamic/DynamicExecution.ps1:4:19:4:25 | Create | Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create |
-| Dynamic/DynamicExecution.ps1:4:26:4:30 | foo | Dynamic/DynamicExecution.ps1:4:4:4:31 | call to Create |
-| Dynamic/DynamicExecution.ps1:5:1:5:8 | call | Dynamic/DynamicExecution.ps1:1:1:5:8 | {...} |
-| Dynamic/DynamicExecution.ps1:5:2:5:8 | $foo | Dynamic/DynamicExecution.ps1:5:1:5:8 | call |
-| Dynamic/DynamicExecution.ps1:5:3:5:7 | foo | Dynamic/DynamicExecution.ps1:5:2:5:8 | $foo |
-| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:2 | ExecuteAThing | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:2 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:2 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:2 | DynamicExecutionWithFunc.ps1 |
-| Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:2 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:2 | ExecuteAThing |
-| Dynamic/DynamicExecutionWithFunc.ps1:2:5:4:6 | param(...) | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:2 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:2 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:3:9:3:19 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:2:5:4:6 | param(...) |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:9 | foo | Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:34 | ...=... |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:34 | ...=... | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:21 | cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:34 | ...+... |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:34 | ...+... | Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:34 | ...=... |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:34 | ...+... | Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:34 | ...+... |
-| Dynamic/DynamicExecutionWithFunc.ps1:5:24:5:34 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:34 | ...+... |
-| Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:22 | Invoke-Expression | Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:27 | call to Invoke-Expression |
-| Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:27 | call to Invoke-Expression | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:6:23:6:27 | foo | Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:27 | call to Invoke-Expression |
-| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:18 | scriptblock | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:7:20:7:26 | Create | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:7:27:7:31 | foo | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:32 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:36 | call | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:7:8:36 | (...) | Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:36 | call |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:21 | scriptblock | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create | Dynamic/DynamicExecutionWithFunc.ps1:8:7:8:36 | (...) |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:23:8:29 | Create | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:8:30:8:34 | foo | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:35 | call to Create |
-| Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:12 | call | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:9:6:9:12 | $foo | Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:12 | call |
-| Dynamic/DynamicExecutionWithFunc.ps1:9:7:9:11 | foo | Dynamic/DynamicExecutionWithFunc.ps1:9:6:9:12 | $foo |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:30 | call to cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:30 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:7:10:16 | cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:30 | call to cmd.exe |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:17:10:30 | @(...) | Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:30 | call to cmd.exe |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:29 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:29 | userInput |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:29 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:29 | {...} |
-| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:29 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:10:17:10:30 | @(...) |
-| Expressions/BinaryExpression.ps1:1:1:1:6 | val1 | Expressions/BinaryExpression.ps1:1:1:1:10 | ...=... |
-| Expressions/BinaryExpression.ps1:1:1:1:10 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:8 | {...} |
-| Expressions/BinaryExpression.ps1:1:1:4:8 | {...} | Expressions/BinaryExpression.ps1:1:1:4:8 | BinaryExpression.ps1 |
-| Expressions/BinaryExpression.ps1:1:9:1:10 | 1 | Expressions/BinaryExpression.ps1:1:1:1:10 | ...=... |
-| Expressions/BinaryExpression.ps1:1:9:1:10 | 1 | Expressions/BinaryExpression.ps1:1:9:1:10 | 1 |
-| Expressions/BinaryExpression.ps1:2:1:2:6 | val2 | Expressions/BinaryExpression.ps1:2:1:2:10 | ...=... |
-| Expressions/BinaryExpression.ps1:2:1:2:10 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:8 | {...} |
-| Expressions/BinaryExpression.ps1:2:9:2:10 | 2 | Expressions/BinaryExpression.ps1:2:1:2:10 | ...=... |
-| Expressions/BinaryExpression.ps1:2:9:2:10 | 2 | Expressions/BinaryExpression.ps1:2:9:2:10 | 2 |
-| Expressions/BinaryExpression.ps1:3:1:3:8 | result | Expressions/BinaryExpression.ps1:3:1:3:24 | ...=... |
-| Expressions/BinaryExpression.ps1:3:1:3:24 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:8 | {...} |
-| Expressions/BinaryExpression.ps1:3:11:3:16 | val1 | Expressions/BinaryExpression.ps1:3:11:3:24 | ...+... |
-| Expressions/BinaryExpression.ps1:3:11:3:24 | ...+... | Expressions/BinaryExpression.ps1:3:1:3:24 | ...=... |
-| Expressions/BinaryExpression.ps1:3:11:3:24 | ...+... | Expressions/BinaryExpression.ps1:3:11:3:24 | ...+... |
-| Expressions/BinaryExpression.ps1:3:19:3:24 | val2 | Expressions/BinaryExpression.ps1:3:11:3:24 | ...+... |
-| Expressions/BinaryExpression.ps1:4:1:4:8 | result | Expressions/BinaryExpression.ps1:1:1:4:8 | {...} |
-| Expressions/BinaryExpression.ps1:4:1:4:8 | result | Expressions/BinaryExpression.ps1:4:1:4:8 | result |
-| Expressions/ConvertWithSecureString.ps1:1:1:1:11 | UserInput | Expressions/ConvertWithSecureString.ps1:1:1:1:55 | ...=... |
-| Expressions/ConvertWithSecureString.ps1:1:1:1:55 | ...=... | Expressions/ConvertWithSecureString.ps1:1:1:2:80 | {...} |
-| Expressions/ConvertWithSecureString.ps1:1:1:2:80 | {...} | Expressions/ConvertWithSecureString.ps1:1:1:2:80 | ConvertWithSecureString.ps1 |
-| Expressions/ConvertWithSecureString.ps1:1:14:1:23 | Read-Host | Expressions/ConvertWithSecureString.ps1:1:14:1:55 | call to Read-Host |
-| Expressions/ConvertWithSecureString.ps1:1:14:1:55 | call to Read-Host | Expressions/ConvertWithSecureString.ps1:1:1:1:55 | ...=... |
-| Expressions/ConvertWithSecureString.ps1:1:24:1:55 | Please enter your secure code | Expressions/ConvertWithSecureString.ps1:1:14:1:55 | call to Read-Host |
-| Expressions/ConvertWithSecureString.ps1:2:1:2:16 | EncryptedInput | Expressions/ConvertWithSecureString.ps1:2:1:2:80 | ...=... |
-| Expressions/ConvertWithSecureString.ps1:2:1:2:80 | ...=... | Expressions/ConvertWithSecureString.ps1:1:1:2:80 | {...} |
-| Expressions/ConvertWithSecureString.ps1:2:19:2:41 | ConvertTo-SecureString | Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString |
-| Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString | Expressions/ConvertWithSecureString.ps1:2:1:2:80 | ...=... |
-| Expressions/ConvertWithSecureString.ps1:2:42:2:49 | String | Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString |
-| Expressions/ConvertWithSecureString.ps1:2:50:2:60 | UserInput | Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString |
-| Expressions/ConvertWithSecureString.ps1:2:61:2:73 | AsPlainText | Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString |
-| Expressions/ConvertWithSecureString.ps1:2:74:2:80 | Force | Expressions/ConvertWithSecureString.ps1:2:19:2:80 | call to ConvertTo-SecureString |
-| Expressions/ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name | Expressions/ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name |
-| Expressions/ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name | Expressions/ExpandableString.ps1:1:1:1:40 | {...} |
-| Expressions/ExpandableString.ps1:1:1:1:40 | {...} | Expressions/ExpandableString.ps1:1:1:1:40 | ExpandableString.ps1 |
-| Expressions/ExpandableString.ps1:1:8:1:13 | name | Expressions/ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name |
-| Expressions/ExpandableString.ps1:1:21:1:39 | $(...) | Expressions/ExpandableString.ps1:1:1:1:40 | Date: $([DateTime]::Now)\nName: $name |
-| Expressions/ExpandableString.ps1:1:23:1:33 | DateTime | Expressions/ExpandableString.ps1:1:23:1:38 | Now |
-| Expressions/ExpandableString.ps1:1:23:1:38 | Now | Expressions/ExpandableString.ps1:1:23:1:38 | Now |
-| Expressions/ExpandableString.ps1:1:23:1:38 | Now | Expressions/ExpandableString.ps1:1:23:1:38 | {...} |
-| Expressions/ExpandableString.ps1:1:23:1:38 | {...} | Expressions/ExpandableString.ps1:1:21:1:39 | $(...) |
-| Expressions/ExpandableString.ps1:1:35:1:38 | Now | Expressions/ExpandableString.ps1:1:23:1:38 | Now |
-| Expressions/SubExpression.ps1:1:1:1:12 | $(...) | Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays |
-| Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays | Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays |
-| Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays | Expressions/SubExpression.ps1:1:1:2:22 | {...} |
-| Expressions/SubExpression.ps1:1:1:2:22 | {...} | Expressions/SubExpression.ps1:1:1:2:22 | SubExpression.ps1 |
-| Expressions/SubExpression.ps1:1:3:1:11 | Get-Date | Expressions/SubExpression.ps1:1:3:1:11 | call to Get-Date |
-| Expressions/SubExpression.ps1:1:3:1:11 | call to Get-Date | Expressions/SubExpression.ps1:1:3:1:11 | {...} |
-| Expressions/SubExpression.ps1:1:3:1:11 | {...} | Expressions/SubExpression.ps1:1:1:1:12 | $(...) |
-| Expressions/SubExpression.ps1:1:13:1:20 | AddDays | Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays |
-| Expressions/SubExpression.ps1:1:21:1:23 | 10 | Expressions/SubExpression.ps1:1:1:1:24 | call to AddDays |
-| Expressions/SubExpression.ps1:2:1:2:12 | $(...) | Expressions/SubExpression.ps1:2:1:2:22 | call to AddDays |
-| Expressions/SubExpression.ps1:2:1:2:22 | call to AddDays | Expressions/SubExpression.ps1:1:1:2:22 | {...} |
-| Expressions/SubExpression.ps1:2:1:2:22 | call to AddDays | Expressions/SubExpression.ps1:2:1:2:22 | call to AddDays |
-| Expressions/SubExpression.ps1:2:3:2:11 | Get-Date | Expressions/SubExpression.ps1:2:3:2:11 | call to Get-Date |
-| Expressions/SubExpression.ps1:2:3:2:11 | call to Get-Date | Expressions/SubExpression.ps1:2:3:2:11 | {...} |
-| Expressions/SubExpression.ps1:2:3:2:11 | {...} | Expressions/SubExpression.ps1:2:1:2:12 | $(...) |
-| Expressions/SubExpression.ps1:2:13:2:20 | AddDays | Expressions/SubExpression.ps1:2:1:2:22 | call to AddDays |
-| Expressions/TernaryExpression.ps1:1:1:1:5 | var | Expressions/TernaryExpression.ps1:1:1:1:23 | ...=... |
-| Expressions/TernaryExpression.ps1:1:1:1:23 | ...=... | Expressions/TernaryExpression.ps1:1:1:1:23 | {...} |
-| Expressions/TernaryExpression.ps1:1:1:1:23 | {...} | Expressions/TernaryExpression.ps1:1:1:1:23 | TernaryExpression.ps1 |
-| Expressions/TernaryExpression.ps1:1:8:1:17 | (...) | Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... |
-| Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... | Expressions/TernaryExpression.ps1:1:1:1:23 | ...=... |
-| Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... | Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... |
-| Expressions/TernaryExpression.ps1:1:9:1:10 | 6 | Expressions/TernaryExpression.ps1:1:9:1:16 | ... -gt ... |
-| Expressions/TernaryExpression.ps1:1:9:1:16 | ... -gt ... | Expressions/TernaryExpression.ps1:1:8:1:17 | (...) |
-| Expressions/TernaryExpression.ps1:1:9:1:16 | ... -gt ... | Expressions/TernaryExpression.ps1:1:9:1:16 | ... -gt ... |
-| Expressions/TernaryExpression.ps1:1:15:1:16 | 7 | Expressions/TernaryExpression.ps1:1:9:1:16 | ... -gt ... |
-| Expressions/TernaryExpression.ps1:1:20:1:21 | 1 | Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... |
-| Expressions/TernaryExpression.ps1:1:22:1:23 | 2 | Expressions/TernaryExpression.ps1:1:8:1:23 | ...?...:... |
-| Loops/DoUntil.ps1:1:1:7:19 | DoUntil | Loops/DoUntil.ps1:1:1:7:19 | {...} |
-| Loops/DoUntil.ps1:1:1:7:19 | {...} | Loops/DoUntil.ps1:1:1:7:19 | DoUntil.ps1 |
-| Loops/DoUntil.ps1:2:1:7:2 | {...} | Loops/DoUntil.ps1:1:1:7:19 | DoUntil |
-| Loops/DoUntil.ps1:3:2:3:20 | Starting Loop $a | Loops/DoUntil.ps1:2:1:7:2 | {...} |
-| Loops/DoUntil.ps1:3:2:3:20 | Starting Loop $a | Loops/DoUntil.ps1:3:2:3:20 | Starting Loop $a |
-| Loops/DoUntil.ps1:3:17:3:19 | a | Loops/DoUntil.ps1:3:2:3:20 | Starting Loop $a |
-| Loops/DoUntil.ps1:4:2:4:4 | a | Loops/DoUntil.ps1:2:1:7:2 | {...} |
-| Loops/DoUntil.ps1:4:2:4:4 | a | Loops/DoUntil.ps1:4:2:4:4 | a |
-| Loops/DoUntil.ps1:5:2:5:4 | a | Loops/DoUntil.ps1:5:2:5:6 | ...++ |
-| Loops/DoUntil.ps1:5:2:5:6 | ...++ | Loops/DoUntil.ps1:2:1:7:2 | {...} |
-| Loops/DoUntil.ps1:5:2:5:6 | ...++ | Loops/DoUntil.ps1:5:2:5:6 | ...++ |
-| Loops/DoUntil.ps1:6:2:6:17 | Now $a is $a | Loops/DoUntil.ps1:2:1:7:2 | {...} |
-| Loops/DoUntil.ps1:6:2:6:17 | Now $a is $a | Loops/DoUntil.ps1:6:2:6:17 | Now $a is $a |
-| Loops/DoUntil.ps1:6:14:6:16 | a | Loops/DoUntil.ps1:6:2:6:17 | Now $a is $a |
-| Loops/DoUntil.ps1:7:10:7:12 | a | Loops/DoUntil.ps1:7:10:7:18 | ... -le ... |
-| Loops/DoUntil.ps1:7:10:7:18 | ... -le ... | Loops/DoUntil.ps1:1:1:7:19 | DoUntil |
-| Loops/DoUntil.ps1:7:10:7:18 | ... -le ... | Loops/DoUntil.ps1:7:10:7:18 | ... -le ... |
-| Loops/DoUntil.ps1:7:17:7:18 | 5 | Loops/DoUntil.ps1:7:10:7:18 | ... -le ... |
-| Loops/DoWhile.ps1:1:1:7:19 | DoWhile | Loops/DoWhile.ps1:1:1:7:19 | {...} |
-| Loops/DoWhile.ps1:1:1:7:19 | {...} | Loops/DoWhile.ps1:1:1:7:19 | DoWhile.ps1 |
-| Loops/DoWhile.ps1:2:1:7:2 | {...} | Loops/DoWhile.ps1:1:1:7:19 | DoWhile |
-| Loops/DoWhile.ps1:3:2:3:20 | Starting Loop $a | Loops/DoWhile.ps1:2:1:7:2 | {...} |
-| Loops/DoWhile.ps1:3:2:3:20 | Starting Loop $a | Loops/DoWhile.ps1:3:2:3:20 | Starting Loop $a |
-| Loops/DoWhile.ps1:3:17:3:19 | a | Loops/DoWhile.ps1:3:2:3:20 | Starting Loop $a |
-| Loops/DoWhile.ps1:4:2:4:4 | a | Loops/DoWhile.ps1:2:1:7:2 | {...} |
-| Loops/DoWhile.ps1:4:2:4:4 | a | Loops/DoWhile.ps1:4:2:4:4 | a |
-| Loops/DoWhile.ps1:5:2:5:4 | a | Loops/DoWhile.ps1:5:2:5:6 | ...++ |
-| Loops/DoWhile.ps1:5:2:5:6 | ...++ | Loops/DoWhile.ps1:2:1:7:2 | {...} |
-| Loops/DoWhile.ps1:5:2:5:6 | ...++ | Loops/DoWhile.ps1:5:2:5:6 | ...++ |
-| Loops/DoWhile.ps1:6:2:6:17 | Now $a is $a | Loops/DoWhile.ps1:2:1:7:2 | {...} |
-| Loops/DoWhile.ps1:6:2:6:17 | Now $a is $a | Loops/DoWhile.ps1:6:2:6:17 | Now $a is $a |
-| Loops/DoWhile.ps1:6:14:6:16 | a | Loops/DoWhile.ps1:6:2:6:17 | Now $a is $a |
-| Loops/DoWhile.ps1:7:10:7:12 | a | Loops/DoWhile.ps1:7:10:7:18 | ... -le ... |
-| Loops/DoWhile.ps1:7:10:7:18 | ... -le ... | Loops/DoWhile.ps1:1:1:7:19 | DoWhile |
-| Loops/DoWhile.ps1:7:10:7:18 | ... -le ... | Loops/DoWhile.ps1:7:10:7:18 | ... -le ... |
-| Loops/DoWhile.ps1:7:17:7:18 | 5 | Loops/DoWhile.ps1:7:10:7:18 | ... -le ... |
-| Loops/While.ps1:1:1:1:5 | var | Loops/While.ps1:1:1:1:9 | ...=... |
-| Loops/While.ps1:1:1:1:9 | ...=... | Loops/While.ps1:1:1:13:2 | {...} |
-| Loops/While.ps1:1:1:13:2 | {...} | Loops/While.ps1:1:1:13:2 | While.ps1 |
-| Loops/While.ps1:1:8:1:9 | 1 | Loops/While.ps1:1:1:1:9 | ...=... |
-| Loops/While.ps1:1:8:1:9 | 1 | Loops/While.ps1:1:8:1:9 | 1 |
-| Loops/While.ps1:2:1:13:2 | while(...) {...} | Loops/While.ps1:1:1:13:2 | {...} |
-| Loops/While.ps1:2:8:2:12 | var | Loops/While.ps1:2:8:2:18 | ... -le ... |
-| Loops/While.ps1:2:8:2:18 | ... -le ... | Loops/While.ps1:2:1:13:2 | while(...) {...} |
-| Loops/While.ps1:2:8:2:18 | ... -le ... | Loops/While.ps1:2:8:2:18 | ... -le ... |
-| Loops/While.ps1:2:17:2:18 | 5 | Loops/While.ps1:2:8:2:18 | ... -le ... |
-| Loops/While.ps1:3:1:13:2 | {...} | Loops/While.ps1:2:1:13:2 | while(...) {...} |
-| Loops/While.ps1:4:5:4:15 | Write-Host | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:5:4:41 | call to Write-Host | Loops/While.ps1:3:1:13:2 | {...} |
-| Loops/While.ps1:4:16:4:19 | The | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:20:4:25 | value | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:26:4:28 | of | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:29:4:32 | Var | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:33:4:36 | is: | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:4:37:4:41 | var | Loops/While.ps1:4:5:4:41 | call to Write-Host |
-| Loops/While.ps1:5:5:5:9 | var | Loops/While.ps1:5:5:5:11 | ...++ |
-| Loops/While.ps1:5:5:5:11 | ...++ | Loops/While.ps1:3:1:13:2 | {...} |
-| Loops/While.ps1:5:5:5:11 | ...++ | Loops/While.ps1:5:5:5:11 | ...++ |
-| Loops/While.ps1:6:5:12:6 | if (...) {...} else {...} | Loops/While.ps1:3:1:13:2 | {...} |
-| Loops/While.ps1:6:9:6:13 | var | Loops/While.ps1:6:9:6:19 | ... -le ... |
-| Loops/While.ps1:6:9:6:19 | ... -le ... | Loops/While.ps1:6:5:12:6 | if (...) {...} else {...} |
-| Loops/While.ps1:6:9:6:19 | ... -le ... | Loops/While.ps1:6:9:6:19 | ... -le ... |
-| Loops/While.ps1:6:18:6:19 | 3 | Loops/While.ps1:6:9:6:19 | ... -le ... |
-| Loops/While.ps1:6:20:8:6 | {...} | Loops/While.ps1:6:5:12:6 | if (...) {...} else {...} |
-| Loops/While.ps1:7:9:7:17 | continue | Loops/While.ps1:6:20:8:6 | {...} |
-| Loops/While.ps1:10:5:12:6 | {...} | Loops/While.ps1:6:5:12:6 | if (...) {...} else {...} |
-| Loops/While.ps1:11:9:11:14 | break | Loops/While.ps1:10:5:12:6 | {...} |
-| Redirections/FileRedirection.ps1:1:1:3:2 | $(...) | Redirections/FileRedirection.ps1:1:1:3:20 | $(...) |
-| Redirections/FileRedirection.ps1:1:1:3:20 | $(...) | Redirections/FileRedirection.ps1:1:1:3:20 | {...} |
-| Redirections/FileRedirection.ps1:1:1:3:20 | {...} | Redirections/FileRedirection.ps1:1:1:3:20 | FileRedirection.ps1 |
-| Redirections/FileRedirection.ps1:2:5:2:9 | Here | Redirections/FileRedirection.ps1:2:5:2:32 | call to Here |
-| Redirections/FileRedirection.ps1:2:5:2:32 | call to Here | Redirections/FileRedirection.ps1:2:5:2:32 | {...} |
-| Redirections/FileRedirection.ps1:2:5:2:32 | {...} | Redirections/FileRedirection.ps1:1:1:3:2 | $(...) |
-| Redirections/FileRedirection.ps1:2:10:2:12 | is | Redirections/FileRedirection.ps1:2:5:2:32 | call to Here |
-| Redirections/FileRedirection.ps1:2:13:2:17 | your | Redirections/FileRedirection.ps1:2:5:2:32 | call to Here |
-| Redirections/FileRedirection.ps1:2:18:2:25 | current | Redirections/FileRedirection.ps1:2:5:2:32 | call to Here |
-| Redirections/FileRedirection.ps1:2:26:2:32 | script | Redirections/FileRedirection.ps1:2:5:2:32 | call to Here |
-| Redirections/FileRedirection.ps1:3:3:3:7 | MergingRedirection | Redirections/FileRedirection.ps1:1:1:3:20 | $(...) |
-| Redirections/FileRedirection.ps1:3:8:3:20 | FileRedirection | Redirections/FileRedirection.ps1:1:1:3:20 | $(...) |
-| Redirections/FileRedirection.ps1:3:10:3:20 | output.txt | Redirections/FileRedirection.ps1:3:8:3:20 | FileRedirection |
-| Statements/ExitStatement.ps1:1:1:1:8 | exit ... | Statements/ExitStatement.ps1:1:1:1:8 | {...} |
-| Statements/ExitStatement.ps1:1:1:1:8 | {...} | Statements/ExitStatement.ps1:1:1:1:8 | ExitStatement.ps1 |
-| Statements/ExitStatement.ps1:1:6:1:8 | -1 | Statements/ExitStatement.ps1:1:1:1:8 | exit ... |
-| Statements/ExitStatement.ps1:1:6:1:8 | -1 | Statements/ExitStatement.ps1:1:6:1:8 | -1 |
-| Statements/IfStatement.ps1:1:1:1:3 | x | Statements/IfStatement.ps1:1:1:1:7 | ...=... |
-| Statements/IfStatement.ps1:1:1:1:7 | ...=... | Statements/IfStatement.ps1:1:1:8:2 | {...} |
-| Statements/IfStatement.ps1:1:1:8:2 | {...} | Statements/IfStatement.ps1:1:1:8:2 | IfStatement.ps1 |
-| Statements/IfStatement.ps1:1:6:1:7 | 4 | Statements/IfStatement.ps1:1:1:1:7 | ...=... |
-| Statements/IfStatement.ps1:1:6:1:7 | 4 | Statements/IfStatement.ps1:1:6:1:7 | 4 |
-| Statements/IfStatement.ps1:3:1:8:2 | if (...) {...} else {...} | Statements/IfStatement.ps1:1:1:8:2 | {...} |
-| Statements/IfStatement.ps1:3:5:3:7 | x | Statements/IfStatement.ps1:3:5:3:13 | ... -ge ... |
-| Statements/IfStatement.ps1:3:5:3:13 | ... -ge ... | Statements/IfStatement.ps1:3:1:8:2 | if (...) {...} else {...} |
-| Statements/IfStatement.ps1:3:5:3:13 | ... -ge ... | Statements/IfStatement.ps1:3:5:3:13 | ... -ge ... |
-| Statements/IfStatement.ps1:3:12:3:13 | 3 | Statements/IfStatement.ps1:3:5:3:13 | ... -ge ... |
-| Statements/IfStatement.ps1:3:15:5:2 | {...} | Statements/IfStatement.ps1:3:1:8:2 | if (...) {...} else {...} |
-| Statements/IfStatement.ps1:4:2:4:36 | $x is greater than or equal to 3 | Statements/IfStatement.ps1:3:15:5:2 | {...} |
-| Statements/IfStatement.ps1:4:2:4:36 | $x is greater than or equal to 3 | Statements/IfStatement.ps1:4:2:4:36 | $x is greater than or equal to 3 |
-| Statements/IfStatement.ps1:4:3:4:5 | x | Statements/IfStatement.ps1:4:2:4:36 | $x is greater than or equal to 3 |
-| Statements/IfStatement.ps1:6:6:8:2 | {...} | Statements/IfStatement.ps1:3:1:8:2 | if (...) {...} else {...} |
-| Statements/IfStatement.ps1:7:2:7:21 | $x is less than 3 | Statements/IfStatement.ps1:6:6:8:2 | {...} |
-| Statements/IfStatement.ps1:7:2:7:21 | $x is less than 3 | Statements/IfStatement.ps1:7:2:7:21 | $x is less than 3 |
-| Statements/IfStatement.ps1:7:3:7:5 | x | Statements/IfStatement.ps1:7:2:7:21 | $x is less than 3 |
-| Statements/TrapStatement.ps1:1:1:4:2 | TrapTest | Statements/TrapStatement.ps1:1:1:6:9 | {...} |
-| Statements/TrapStatement.ps1:1:1:6:9 | {...} | Statements/TrapStatement.ps1:1:1:6:9 | TrapStatement.ps1 |
-| Statements/TrapStatement.ps1:1:19:4:2 | {...} | Statements/TrapStatement.ps1:1:1:4:2 | TrapTest |
-| Statements/TrapStatement.ps1:2:5:2:26 | TrapStatement at: Statements/TrapStatement.ps1:2:5:2:26 | Statements/TrapStatement.ps1:2:5:3:19 | {...} |
-| Statements/TrapStatement.ps1:2:5:3:19 | {...} | Statements/TrapStatement.ps1:1:19:4:2 | {...} |
-| Statements/TrapStatement.ps1:2:10:2:26 | {...} | Statements/TrapStatement.ps1:2:5:2:26 | TrapStatement at: Statements/TrapStatement.ps1:2:5:2:26 |
-| Statements/TrapStatement.ps1:2:11:2:25 | Error found. | Statements/TrapStatement.ps1:2:10:2:26 | {...} |
-| Statements/TrapStatement.ps1:2:11:2:25 | Error found. | Statements/TrapStatement.ps1:2:11:2:25 | Error found. |
-| Statements/TrapStatement.ps1:3:5:3:19 | call to nonsenseString | Statements/TrapStatement.ps1:2:5:3:19 | {...} |
-| Statements/TrapStatement.ps1:3:5:3:19 | nonsenseString | Statements/TrapStatement.ps1:3:5:3:19 | call to nonsenseString |
-| Statements/TrapStatement.ps1:6:1:6:9 | TrapTest | Statements/TrapStatement.ps1:6:1:6:9 | call to TrapTest |
-| Statements/TrapStatement.ps1:6:1:6:9 | call to TrapTest | Statements/TrapStatement.ps1:1:1:6:9 | {...} |
-| Statements/Try.ps1:1:1:13:2 | try {...} | Statements/Try.ps1:1:1:13:2 | {...} |
-| Statements/Try.ps1:1:1:13:2 | {...} | Statements/Try.ps1:1:1:13:2 | Try.ps1 |
-| Statements/Try.ps1:1:5:4:2 | {...} | Statements/Try.ps1:1:1:13:2 | try {...} |
-| Statements/Try.ps1:2:4:2:14 | Exception | Statements/Try.ps1:2:4:2:95 | ...=... |
-| Statements/Try.ps1:2:4:2:95 | ...=... | Statements/Try.ps1:1:5:4:2 | {...} |
-| Statements/Try.ps1:2:17:2:27 | New-Object | Statements/Try.ps1:2:17:2:95 | call to New-Object |
-| Statements/Try.ps1:2:17:2:95 | call to New-Object | Statements/Try.ps1:2:4:2:95 | ...=... |
-| Statements/Try.ps1:2:28:2:53 | System.Xaml.XamlException | Statements/Try.ps1:2:17:2:95 | call to New-Object |
-| Statements/Try.ps1:2:54:2:67 | ArgumentList | Statements/Try.ps1:2:17:2:95 | call to New-Object |
-| Statements/Try.ps1:2:68:2:95 | (...) | Statements/Try.ps1:2:17:2:95 | call to New-Object |
-| Statements/Try.ps1:2:69:2:80 | Bad XAML! | Statements/Try.ps1:2:69:2:94 | ...,... |
-| Statements/Try.ps1:2:69:2:94 | ...,... | Statements/Try.ps1:2:68:2:95 | (...) |
-| Statements/Try.ps1:2:69:2:94 | ...,... | Statements/Try.ps1:2:69:2:94 | ...,... |
-| Statements/Try.ps1:2:82:2:87 | null | Statements/Try.ps1:2:69:2:94 | ...,... |
-| Statements/Try.ps1:2:89:2:91 | 10 | Statements/Try.ps1:2:69:2:94 | ...,... |
-| Statements/Try.ps1:2:93:2:94 | 2 | Statements/Try.ps1:2:69:2:94 | ...,... |
-| Statements/Try.ps1:3:5:3:21 | throw ... | Statements/Try.ps1:1:5:4:2 | {...} |
-| Statements/Try.ps1:3:11:3:21 | Exception | Statements/Try.ps1:3:5:3:21 | throw ... |
-| Statements/Try.ps1:3:11:3:21 | Exception | Statements/Try.ps1:3:11:3:21 | Exception |
-| Statements/Try.ps1:5:1:7:2 | catch[...] {...} | Statements/Try.ps1:1:1:13:2 | try {...} |
-| Statements/Try.ps1:5:7:5:32 | System.Net.WebException | Statements/Try.ps1:5:1:7:2 | catch[...] {...} |
-| Statements/Try.ps1:5:33:5:56 | System.IO.IOException | Statements/Try.ps1:5:1:7:2 | catch[...] {...} |
-| Statements/Try.ps1:5:57:7:2 | {...} | Statements/Try.ps1:5:1:7:2 | catch[...] {...} |
-| Statements/Try.ps1:6:5:6:64 | Unable to download MyDoc.doc from http://www.contoso.com. | Statements/Try.ps1:5:57:7:2 | {...} |
-| Statements/Try.ps1:6:5:6:64 | Unable to download MyDoc.doc from http://www.contoso.com. | Statements/Try.ps1:6:5:6:64 | Unable to download MyDoc.doc from http://www.contoso.com. |
-| Statements/Try.ps1:8:1:10:2 | catch {...} | Statements/Try.ps1:1:1:13:2 | try {...} |
-| Statements/Try.ps1:8:7:10:2 | {...} | Statements/Try.ps1:8:1:10:2 | catch {...} |
-| Statements/Try.ps1:9:5:9:52 | An error occurred that could not be resolved. | Statements/Try.ps1:8:7:10:2 | {...} |
-| Statements/Try.ps1:9:5:9:52 | An error occurred that could not be resolved. | Statements/Try.ps1:9:5:9:52 | An error occurred that could not be resolved. |
-| Statements/Try.ps1:11:9:13:2 | {...} | Statements/Try.ps1:1:1:13:2 | try {...} |
-| Statements/Try.ps1:12:5:12:37 | The finally block is executed. | Statements/Try.ps1:11:9:13:2 | {...} |
-| Statements/Try.ps1:12:5:12:37 | The finally block is executed. | Statements/Try.ps1:12:5:12:37 | The finally block is executed. |
-| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | Get-Number | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | {...} |
-| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | UseProcessBlockForPipelineCommand.ps1 |
-| Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:2 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:2 | Get-Number |
-| Statements/UseProcessBlockForPipelineCommand.ps1:3:5:3:22 | CmdletBinding | Statements/UseProcessBlockForPipelineCommand.ps1:4:5:8:6 | param(...) |
-| Statements/UseProcessBlockForPipelineCommand.ps1:4:5:8:6 | param(...) | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:2 | {...} |
-| Statements/UseProcessBlockForPipelineCommand.ps1:4:5:10:12 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:2 | {...} |
-| Statements/UseProcessBlockForPipelineCommand.ps1:5:9:5:39 | Parameter | Statements/UseProcessBlockForPipelineCommand.ps1:5:9:7:16 | Number |
-| Statements/UseProcessBlockForPipelineCommand.ps1:5:9:7:16 | Number | Statements/UseProcessBlockForPipelineCommand.ps1:4:5:8:6 | param(...) |
-| Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:37 | True | Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:37 | ValueFromPipeline |
-| Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:37 | ValueFromPipeline | Statements/UseProcessBlockForPipelineCommand.ps1:5:9:5:39 | Parameter |
-| Statements/UseProcessBlockForPipelineCommand.ps1:6:9:6:14 | int | Statements/UseProcessBlockForPipelineCommand.ps1:5:9:7:16 | Number |
-| Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:12 | Number | Statements/UseProcessBlockForPipelineCommand.ps1:4:5:10:12 | {...} |
-| Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:12 | Number | Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:12 | Number |
-| file://:0:0:0:0 | (no string representation) | Blocks/ParamBlock.ps1:3:5:4:23 | Parameter |
-| file://:0:0:0:0 | (no string representation) | Dynamic/DynamicExecutionWithFunc.ps1:3:9:3:19 | userInput |
-| file://:0:0:0:0 | (no string representation) | Statements/UseProcessBlockForPipelineCommand.ps1:5:9:7:16 | Number |
+| Arrays/Arrays.ps1:0:0:0:-1 | {...} | Arrays/Arrays.ps1:14:41:14:43 | @(...) |
+| Arrays/Arrays.ps1:1:1:1:7 | array1 | Arrays/Arrays.ps1:1:1:1:36 | ...=... |
+| Arrays/Arrays.ps1:1:1:1:7 | array1 | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:1:1:1:36 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:1:1:15:14 | {...} | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:1:1:15:14 | {...} | file://:0:0:0:0 | toplevel function for Arrays.ps1 |
+| Arrays/Arrays.ps1:1:11:1:11 | 1 | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:1:11:1:36 | ...,... | Arrays/Arrays.ps1:1:1:1:36 | ...=... |
+| Arrays/Arrays.ps1:1:13:1:13 | 2 | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:1:15:1:17 | a | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:1:19:1:23 | true | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:1:25:1:30 | false | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:1:32:1:36 | null | Arrays/Arrays.ps1:1:11:1:36 | ...,... |
+| Arrays/Arrays.ps1:2:1:2:7 | array1 | Arrays/Arrays.ps1:2:1:2:10 | ...[...] |
+| Arrays/Arrays.ps1:2:1:2:10 | ...[...] | Arrays/Arrays.ps1:2:1:2:14 | ...=... |
+| Arrays/Arrays.ps1:2:1:2:14 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:2:9:2:9 | 1 | Arrays/Arrays.ps1:2:1:2:10 | ...[...] |
+| Arrays/Arrays.ps1:2:14:2:14 | 3 | Arrays/Arrays.ps1:2:1:2:14 | ...=... |
+| Arrays/Arrays.ps1:3:1:3:7 | array1 | Arrays/Arrays.ps1:3:1:3:10 | ...[...] |
+| Arrays/Arrays.ps1:3:1:3:10 | ...[...] | Arrays/Arrays.ps1:3:1:3:16 | ...=... |
+| Arrays/Arrays.ps1:3:1:3:16 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:3:9:3:9 | 2 | Arrays/Arrays.ps1:3:1:3:10 | ...[...] |
+| Arrays/Arrays.ps1:3:14:3:16 | b | Arrays/Arrays.ps1:3:1:3:16 | ...=... |
+| Arrays/Arrays.ps1:5:1:5:7 | array2 | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:5:1:5:7 | array2 | Arrays/Arrays.ps1:5:1:5:36 | ...=... |
+| Arrays/Arrays.ps1:5:1:5:36 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:5:11:5:20 | New-Object | Arrays/Arrays.ps1:5:11:5:36 | Call to New-Object |
+| Arrays/Arrays.ps1:5:11:5:36 | Call to New-Object | Arrays/Arrays.ps1:5:1:5:36 | ...=... |
+| Arrays/Arrays.ps1:5:22:5:32 | object[,] | Arrays/Arrays.ps1:5:11:5:36 | Call to New-Object |
+| Arrays/Arrays.ps1:5:34:5:34 | 2 | Arrays/Arrays.ps1:5:34:5:36 | ...,... |
+| Arrays/Arrays.ps1:5:34:5:36 | ...,... | Arrays/Arrays.ps1:5:11:5:36 | Call to New-Object |
+| Arrays/Arrays.ps1:5:36:5:36 | 2 | Arrays/Arrays.ps1:5:34:5:36 | ...,... |
+| Arrays/Arrays.ps1:6:1:6:7 | array2 | Arrays/Arrays.ps1:6:1:6:12 | ...[...] |
+| Arrays/Arrays.ps1:6:1:6:12 | ...[...] | Arrays/Arrays.ps1:6:1:6:21 | ...=... |
+| Arrays/Arrays.ps1:6:1:6:21 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:6:9:6:9 | 0 | Arrays/Arrays.ps1:6:9:6:11 | ...,... |
+| Arrays/Arrays.ps1:6:9:6:11 | ...,... | Arrays/Arrays.ps1:6:1:6:12 | ...[...] |
+| Arrays/Arrays.ps1:6:11:6:11 | 0 | Arrays/Arrays.ps1:6:9:6:11 | ...,... |
+| Arrays/Arrays.ps1:6:16:6:21 | key1 | Arrays/Arrays.ps1:6:1:6:21 | ...=... |
+| Arrays/Arrays.ps1:7:1:7:7 | array2 | Arrays/Arrays.ps1:7:1:7:12 | ...[...] |
+| Arrays/Arrays.ps1:7:1:7:12 | ...[...] | Arrays/Arrays.ps1:7:1:7:21 | ...=... |
+| Arrays/Arrays.ps1:7:1:7:21 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:7:9:7:9 | 1 | Arrays/Arrays.ps1:7:9:7:11 | ...,... |
+| Arrays/Arrays.ps1:7:9:7:11 | ...,... | Arrays/Arrays.ps1:7:1:7:12 | ...[...] |
+| Arrays/Arrays.ps1:7:11:7:11 | 0 | Arrays/Arrays.ps1:7:9:7:11 | ...,... |
+| Arrays/Arrays.ps1:7:16:7:21 | key1 | Arrays/Arrays.ps1:7:1:7:21 | ...=... |
+| Arrays/Arrays.ps1:8:1:8:7 | array2 | Arrays/Arrays.ps1:8:1:8:12 | ...[...] |
+| Arrays/Arrays.ps1:8:1:8:12 | ...[...] | Arrays/Arrays.ps1:8:1:8:23 | ...=... |
+| Arrays/Arrays.ps1:8:1:8:23 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:8:9:8:9 | 0 | Arrays/Arrays.ps1:8:9:8:11 | ...,... |
+| Arrays/Arrays.ps1:8:9:8:11 | ...,... | Arrays/Arrays.ps1:8:1:8:12 | ...[...] |
+| Arrays/Arrays.ps1:8:11:8:11 | 1 | Arrays/Arrays.ps1:8:9:8:11 | ...,... |
+| Arrays/Arrays.ps1:8:16:8:23 | value1 | Arrays/Arrays.ps1:8:1:8:23 | ...=... |
+| Arrays/Arrays.ps1:9:1:9:7 | array2 | Arrays/Arrays.ps1:9:1:9:12 | ...[...] |
+| Arrays/Arrays.ps1:9:1:9:12 | ...[...] | Arrays/Arrays.ps1:9:1:9:20 | ...=... |
+| Arrays/Arrays.ps1:9:1:9:20 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:9:9:9:9 | 1 | Arrays/Arrays.ps1:9:9:9:11 | ...,... |
+| Arrays/Arrays.ps1:9:9:9:11 | ...,... | Arrays/Arrays.ps1:9:1:9:12 | ...[...] |
+| Arrays/Arrays.ps1:9:11:9:11 | 1 | Arrays/Arrays.ps1:9:9:9:11 | ...,... |
+| Arrays/Arrays.ps1:9:16:9:20 | null | Arrays/Arrays.ps1:9:1:9:20 | ...=... |
+| Arrays/Arrays.ps1:11:1:11:7 | array3 | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:11:1:11:7 | array3 | Arrays/Arrays.ps1:11:1:11:24 | ...=... |
+| Arrays/Arrays.ps1:11:1:11:24 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:11:11:11:24 | @(...) | Arrays/Arrays.ps1:11:1:11:24 | ...=... |
+| Arrays/Arrays.ps1:11:13:11:15 | a | Arrays/Arrays.ps1:11:13:11:23 | ...,... |
+| Arrays/Arrays.ps1:11:13:11:23 | ...,... | Arrays/Arrays.ps1:11:13:11:23 | [Stmt] ...,... |
+| Arrays/Arrays.ps1:11:13:11:23 | [Stmt] ...,... | Arrays/Arrays.ps1:11:13:11:23 | {...} |
+| Arrays/Arrays.ps1:11:13:11:23 | {...} | Arrays/Arrays.ps1:11:11:11:24 | @(...) |
+| Arrays/Arrays.ps1:11:17:11:19 | b | Arrays/Arrays.ps1:11:13:11:23 | ...,... |
+| Arrays/Arrays.ps1:11:21:11:23 | c | Arrays/Arrays.ps1:11:13:11:23 | ...,... |
+| Arrays/Arrays.ps1:12:1:12:7 | array3 | Arrays/Arrays.ps1:12:1:12:13 | count |
+| Arrays/Arrays.ps1:12:1:12:13 | [Stmt] count | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:12:1:12:13 | count | Arrays/Arrays.ps1:12:1:12:13 | [Stmt] count |
+| Arrays/Arrays.ps1:12:9:12:13 | count | Arrays/Arrays.ps1:12:1:12:13 | count |
+| Arrays/Arrays.ps1:14:1:14:7 | array4 | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:14:1:14:7 | array4 | Arrays/Arrays.ps1:14:1:14:43 | ...=... |
+| Arrays/Arrays.ps1:14:1:14:43 | ...=... | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:14:11:14:40 | System.Collections.ArrayList | Arrays/Arrays.ps1:14:11:14:43 | [...]... |
+| Arrays/Arrays.ps1:14:11:14:43 | [...]... | Arrays/Arrays.ps1:14:1:14:43 | ...=... |
+| Arrays/Arrays.ps1:14:41:14:43 | @(...) | Arrays/Arrays.ps1:14:11:14:43 | [...]... |
+| Arrays/Arrays.ps1:15:1:15:7 | array4 | Arrays/Arrays.ps1:15:1:15:14 | Call to Add |
+| Arrays/Arrays.ps1:15:1:15:14 | Call to Add | Arrays/Arrays.ps1:15:1:15:14 | [Stmt] Call to Add |
+| Arrays/Arrays.ps1:15:1:15:14 | [Stmt] Call to Add | Arrays/Arrays.ps1:1:1:15:14 | {...} |
+| Arrays/Arrays.ps1:15:9:15:11 | Add | Arrays/Arrays.ps1:15:1:15:14 | Call to Add |
+| Arrays/Arrays.ps1:15:13:15:13 | 1 | Arrays/Arrays.ps1:15:1:15:14 | Call to Add |
+| Blocks/ParamBlock.ps1:1:1:1:17 | CmdletBinding | Blocks/ParamBlock.ps1:1:1:5:1 | {...} |
+| Blocks/ParamBlock.ps1:1:1:5:1 | Parameter | Blocks/ParamBlock.ps1:1:1:5:1 | {...} |
+| Blocks/ParamBlock.ps1:1:1:5:1 | [synth] pipeline | Blocks/ParamBlock.ps1:1:1:5:1 | {...} |
+| Blocks/ParamBlock.ps1:1:1:5:1 | {...} | file://:0:0:0:0 | toplevel function for ParamBlock.ps1 |
+| Blocks/ParamBlock.ps1:2:1:5:1 | {...} | Blocks/ParamBlock.ps1:1:1:5:1 | {...} |
+| Blocks/ParamBlock.ps1:3:5:3:17 | Parameter | Blocks/ParamBlock.ps1:1:1:5:1 | Parameter |
+| Blocks/ParamBlock.ps1:4:5:4:12 | string | Blocks/ParamBlock.ps1:1:1:5:1 | Parameter |
+| Dynamic/DynamicExecution.ps1:1:1:1:4 | foo | Dynamic/DynamicExecution.ps1:1:1:1:16 | ...=... |
+| Dynamic/DynamicExecution.ps1:1:1:1:4 | foo | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:1:1:1:16 | ...=... | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} | file://:0:0:0:0 | toplevel function for DynamicExecution.ps1 |
+| Dynamic/DynamicExecution.ps1:1:8:1:16 | cmd.exe | Dynamic/DynamicExecution.ps1:1:1:1:16 | ...=... |
+| Dynamic/DynamicExecution.ps1:2:1:2:17 | Invoke-Expression | Dynamic/DynamicExecution.ps1:2:1:2:22 | Call to Invoke-Expression |
+| Dynamic/DynamicExecution.ps1:2:1:2:22 | Call to Invoke-Expression | Dynamic/DynamicExecution.ps1:2:1:2:22 | [Stmt] Call to Invoke-Expression |
+| Dynamic/DynamicExecution.ps1:2:1:2:22 | [Stmt] Call to Invoke-Expression | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:2:19:2:22 | foo | Dynamic/DynamicExecution.ps1:2:1:2:22 | Call to Invoke-Expression |
+| Dynamic/DynamicExecution.ps1:3:1:3:13 | scriptblock | Dynamic/DynamicExecution.ps1:3:1:3:27 | Call to Create |
+| Dynamic/DynamicExecution.ps1:3:1:3:27 | Call to Create | Dynamic/DynamicExecution.ps1:3:1:3:27 | [Stmt] Call to Create |
+| Dynamic/DynamicExecution.ps1:3:1:3:27 | [Stmt] Call to Create | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:3:16:3:21 | Create | Dynamic/DynamicExecution.ps1:3:1:3:27 | Call to Create |
+| Dynamic/DynamicExecution.ps1:3:23:3:26 | foo | Dynamic/DynamicExecution.ps1:3:1:3:27 | Call to Create |
+| Dynamic/DynamicExecution.ps1:4:1:4:31 | Call to | Dynamic/DynamicExecution.ps1:4:1:4:31 | [Stmt] Call to |
+| Dynamic/DynamicExecution.ps1:4:1:4:31 | [Stmt] Call to | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:4:3:4:31 | (...) | Dynamic/DynamicExecution.ps1:4:1:4:31 | Call to |
+| Dynamic/DynamicExecution.ps1:4:4:4:16 | scriptblock | Dynamic/DynamicExecution.ps1:4:4:4:30 | Call to Create |
+| Dynamic/DynamicExecution.ps1:4:4:4:30 | Call to Create | Dynamic/DynamicExecution.ps1:4:3:4:31 | (...) |
+| Dynamic/DynamicExecution.ps1:4:19:4:24 | Create | Dynamic/DynamicExecution.ps1:4:4:4:30 | Call to Create |
+| Dynamic/DynamicExecution.ps1:4:26:4:29 | foo | Dynamic/DynamicExecution.ps1:4:4:4:30 | Call to Create |
+| Dynamic/DynamicExecution.ps1:5:1:5:7 | Call to | Dynamic/DynamicExecution.ps1:5:1:5:7 | [Stmt] Call to |
+| Dynamic/DynamicExecution.ps1:5:1:5:7 | [Stmt] Call to | Dynamic/DynamicExecution.ps1:1:1:5:7 | {...} |
+| Dynamic/DynamicExecution.ps1:5:2:5:7 | $foo | Dynamic/DynamicExecution.ps1:5:1:5:7 | Call to |
+| Dynamic/DynamicExecution.ps1:5:3:5:6 | foo | Dynamic/DynamicExecution.ps1:5:2:5:7 | $foo |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | ExecuteAThing | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | def of ExecuteAThing |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | def of ExecuteAThing | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | {...} | file://:0:0:0:0 | toplevel function for DynamicExecutionWithFunc.ps1 |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | [synth] pipeline | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:1:11:1 | ExecuteAThing |
+| Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:8 | foo | Dynamic/DynamicExecutionWithFunc.ps1:1:24:11:1 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:8 | foo | Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:33 | ...=... |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:33 | ...=... | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:20 | cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:33 | ...+... |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:33 | ...+... | Dynamic/DynamicExecutionWithFunc.ps1:5:5:5:33 | ...=... |
+| Dynamic/DynamicExecutionWithFunc.ps1:5:24:5:33 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:5:12:5:33 | ...+... |
+| Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:21 | Invoke-Expression | Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:26 | Call to Invoke-Expression |
+| Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:26 | Call to Invoke-Expression | Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:26 | [Stmt] Call to Invoke-Expression |
+| Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:26 | [Stmt] Call to Invoke-Expression | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:6:23:6:26 | foo | Dynamic/DynamicExecutionWithFunc.ps1:6:5:6:26 | Call to Invoke-Expression |
+| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:17 | scriptblock | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | Call to Create | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | [Stmt] Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | [Stmt] Call to Create | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:7:20:7:25 | Create | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:7:27:7:30 | foo | Dynamic/DynamicExecutionWithFunc.ps1:7:5:7:31 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:35 | Call to | Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:35 | [Stmt] Call to |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:35 | [Stmt] Call to | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:7:8:35 | (...) | Dynamic/DynamicExecutionWithFunc.ps1:8:5:8:35 | Call to |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:20 | scriptblock | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:34 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:34 | Call to Create | Dynamic/DynamicExecutionWithFunc.ps1:8:7:8:35 | (...) |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:23:8:28 | Create | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:34 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:8:30:8:33 | foo | Dynamic/DynamicExecutionWithFunc.ps1:8:8:8:34 | Call to Create |
+| Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:11 | Call to | Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:11 | [Stmt] Call to |
+| Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:11 | [Stmt] Call to | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:9:6:9:11 | $foo | Dynamic/DynamicExecutionWithFunc.ps1:9:5:9:11 | Call to |
+| Dynamic/DynamicExecutionWithFunc.ps1:9:7:9:10 | foo | Dynamic/DynamicExecutionWithFunc.ps1:9:6:9:11 | $foo |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:29 | Call to cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:29 | [Stmt] Call to cmd.exe |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:29 | [Stmt] Call to cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:2:5:10:29 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:7:10:15 | cmd.exe | Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:29 | Call to cmd.exe |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:17:10:29 | @(...) | Dynamic/DynamicExecutionWithFunc.ps1:10:5:10:29 | Call to cmd.exe |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:28 | [Stmt] userInput | Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:28 | {...} |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:28 | userInput | Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:28 | [Stmt] userInput |
+| Dynamic/DynamicExecutionWithFunc.ps1:10:19:10:28 | {...} | Dynamic/DynamicExecutionWithFunc.ps1:10:17:10:29 | @(...) |
+| Expressions/BinaryExpression.ps1:1:1:1:5 | val1 | Expressions/BinaryExpression.ps1:1:1:1:9 | ...=... |
+| Expressions/BinaryExpression.ps1:1:1:1:5 | val1 | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:1:1:1:9 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:1:1:4:7 | {...} | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:1:1:4:7 | {...} | file://:0:0:0:0 | toplevel function for BinaryExpression.ps1 |
+| Expressions/BinaryExpression.ps1:1:9:1:9 | 1 | Expressions/BinaryExpression.ps1:1:1:1:9 | ...=... |
+| Expressions/BinaryExpression.ps1:2:1:2:5 | val2 | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:2:1:2:5 | val2 | Expressions/BinaryExpression.ps1:2:1:2:9 | ...=... |
+| Expressions/BinaryExpression.ps1:2:1:2:9 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:2:9:2:9 | 2 | Expressions/BinaryExpression.ps1:2:1:2:9 | ...=... |
+| Expressions/BinaryExpression.ps1:3:1:3:7 | result | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:3:1:3:7 | result | Expressions/BinaryExpression.ps1:3:1:3:23 | ...=... |
+| Expressions/BinaryExpression.ps1:3:1:3:23 | ...=... | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:3:11:3:15 | val1 | Expressions/BinaryExpression.ps1:3:11:3:23 | ...+... |
+| Expressions/BinaryExpression.ps1:3:11:3:23 | ...+... | Expressions/BinaryExpression.ps1:3:1:3:23 | ...=... |
+| Expressions/BinaryExpression.ps1:3:19:3:23 | val2 | Expressions/BinaryExpression.ps1:3:11:3:23 | ...+... |
+| Expressions/BinaryExpression.ps1:4:1:4:7 | [Stmt] result | Expressions/BinaryExpression.ps1:1:1:4:7 | {...} |
+| Expressions/BinaryExpression.ps1:4:1:4:7 | result | Expressions/BinaryExpression.ps1:4:1:4:7 | [Stmt] result |
+| Expressions/ConvertWithSecureString.ps1:1:1:1:10 | UserInput | Expressions/ConvertWithSecureString.ps1:1:1:1:54 | ...=... |
+| Expressions/ConvertWithSecureString.ps1:1:1:1:10 | UserInput | Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} |
+| Expressions/ConvertWithSecureString.ps1:1:1:1:54 | ...=... | Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} |
+| Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} | Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} |
+| Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} | file://:0:0:0:0 | toplevel function for ConvertWithSecureString.ps1 |
+| Expressions/ConvertWithSecureString.ps1:1:14:1:22 | Read-Host | Expressions/ConvertWithSecureString.ps1:1:14:1:54 | Call to Read-Host |
+| Expressions/ConvertWithSecureString.ps1:1:14:1:54 | Call to Read-Host | Expressions/ConvertWithSecureString.ps1:1:1:1:54 | ...=... |
+| Expressions/ConvertWithSecureString.ps1:1:24:1:54 | Please enter your secure code | Expressions/ConvertWithSecureString.ps1:1:14:1:54 | Call to Read-Host |
+| Expressions/ConvertWithSecureString.ps1:2:1:2:15 | EncryptedInput | Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} |
+| Expressions/ConvertWithSecureString.ps1:2:1:2:15 | EncryptedInput | Expressions/ConvertWithSecureString.ps1:2:1:2:79 | ...=... |
+| Expressions/ConvertWithSecureString.ps1:2:1:2:79 | ...=... | Expressions/ConvertWithSecureString.ps1:1:1:2:79 | {...} |
+| Expressions/ConvertWithSecureString.ps1:2:19:2:40 | ConvertTo-SecureString | Expressions/ConvertWithSecureString.ps1:2:19:2:79 | Call to ConvertTo-SecureString |
+| Expressions/ConvertWithSecureString.ps1:2:19:2:79 | Call to ConvertTo-SecureString | Expressions/ConvertWithSecureString.ps1:2:1:2:79 | ...=... |
+| Expressions/ConvertWithSecureString.ps1:2:50:2:59 | UserInput | Expressions/ConvertWithSecureString.ps1:2:19:2:79 | Call to ConvertTo-SecureString |
+| Expressions/ExpandableString.ps1:1:1:1:39 | Date: $([DateTime]::Now)\nName: $name | Expressions/ExpandableString.ps1:1:1:1:39 | [Stmt] Date: $([DateTime]::Now)\nName: $name |
+| Expressions/ExpandableString.ps1:1:1:1:39 | [Stmt] Date: $([DateTime]::Now)\nName: $name | Expressions/ExpandableString.ps1:1:1:1:39 | {...} |
+| Expressions/ExpandableString.ps1:1:1:1:39 | {...} | Expressions/ExpandableString.ps1:1:1:1:39 | {...} |
+| Expressions/ExpandableString.ps1:1:1:1:39 | {...} | file://:0:0:0:0 | toplevel function for ExpandableString.ps1 |
+| Expressions/ExpandableString.ps1:1:21:1:38 | $(...) | Expressions/ExpandableString.ps1:1:1:1:39 | Date: $([DateTime]::Now)\nName: $name |
+| Expressions/ExpandableString.ps1:1:23:1:32 | DateTime | Expressions/ExpandableString.ps1:1:23:1:37 | Now |
+| Expressions/ExpandableString.ps1:1:23:1:37 | Now | Expressions/ExpandableString.ps1:1:23:1:37 | [Stmt] Now |
+| Expressions/ExpandableString.ps1:1:23:1:37 | [Stmt] Now | Expressions/ExpandableString.ps1:1:23:1:37 | {...} |
+| Expressions/ExpandableString.ps1:1:23:1:37 | {...} | Expressions/ExpandableString.ps1:1:21:1:38 | $(...) |
+| Expressions/ExpandableString.ps1:1:35:1:37 | Now | Expressions/ExpandableString.ps1:1:23:1:37 | Now |
+| Expressions/SubExpression.ps1:1:1:1:11 | $(...) | Expressions/SubExpression.ps1:1:1:1:23 | Call to AddDays |
+| Expressions/SubExpression.ps1:1:1:1:23 | Call to AddDays | Expressions/SubExpression.ps1:1:1:1:23 | [Stmt] Call to AddDays |
+| Expressions/SubExpression.ps1:1:1:1:23 | [Stmt] Call to AddDays | Expressions/SubExpression.ps1:1:1:2:21 | {...} |
+| Expressions/SubExpression.ps1:1:1:2:21 | {...} | Expressions/SubExpression.ps1:1:1:2:21 | {...} |
+| Expressions/SubExpression.ps1:1:1:2:21 | {...} | file://:0:0:0:0 | toplevel function for SubExpression.ps1 |
+| Expressions/SubExpression.ps1:1:3:1:10 | Call to Get-Date | Expressions/SubExpression.ps1:1:3:1:10 | [Stmt] Call to Get-Date |
+| Expressions/SubExpression.ps1:1:3:1:10 | Get-Date | Expressions/SubExpression.ps1:1:3:1:10 | Call to Get-Date |
+| Expressions/SubExpression.ps1:1:3:1:10 | [Stmt] Call to Get-Date | Expressions/SubExpression.ps1:1:3:1:10 | {...} |
+| Expressions/SubExpression.ps1:1:3:1:10 | {...} | Expressions/SubExpression.ps1:1:1:1:11 | $(...) |
+| Expressions/SubExpression.ps1:1:13:1:19 | AddDays | Expressions/SubExpression.ps1:1:1:1:23 | Call to AddDays |
+| Expressions/SubExpression.ps1:1:21:1:22 | 10 | Expressions/SubExpression.ps1:1:1:1:23 | Call to AddDays |
+| Expressions/SubExpression.ps1:2:1:2:11 | $(...) | Expressions/SubExpression.ps1:2:1:2:21 | Call to AddDays |
+| Expressions/SubExpression.ps1:2:1:2:21 | Call to AddDays | Expressions/SubExpression.ps1:2:1:2:21 | [Stmt] Call to AddDays |
+| Expressions/SubExpression.ps1:2:1:2:21 | [Stmt] Call to AddDays | Expressions/SubExpression.ps1:1:1:2:21 | {...} |
+| Expressions/SubExpression.ps1:2:3:2:10 | Call to Get-Date | Expressions/SubExpression.ps1:2:3:2:10 | [Stmt] Call to Get-Date |
+| Expressions/SubExpression.ps1:2:3:2:10 | Get-Date | Expressions/SubExpression.ps1:2:3:2:10 | Call to Get-Date |
+| Expressions/SubExpression.ps1:2:3:2:10 | [Stmt] Call to Get-Date | Expressions/SubExpression.ps1:2:3:2:10 | {...} |
+| Expressions/SubExpression.ps1:2:3:2:10 | {...} | Expressions/SubExpression.ps1:2:1:2:11 | $(...) |
+| Expressions/SubExpression.ps1:2:13:2:19 | AddDays | Expressions/SubExpression.ps1:2:1:2:21 | Call to AddDays |
+| Expressions/TernaryExpression.ps1:1:1:1:4 | var | Expressions/TernaryExpression.ps1:1:1:1:22 | ...=... |
+| Expressions/TernaryExpression.ps1:1:1:1:4 | var | Expressions/TernaryExpression.ps1:1:1:1:22 | {...} |
+| Expressions/TernaryExpression.ps1:1:1:1:22 | ...=... | Expressions/TernaryExpression.ps1:1:1:1:22 | {...} |
+| Expressions/TernaryExpression.ps1:1:1:1:22 | {...} | Expressions/TernaryExpression.ps1:1:1:1:22 | {...} |
+| Expressions/TernaryExpression.ps1:1:1:1:22 | {...} | file://:0:0:0:0 | toplevel function for TernaryExpression.ps1 |
+| Expressions/TernaryExpression.ps1:1:8:1:16 | (...) | Expressions/TernaryExpression.ps1:1:8:1:22 | ...?...:... |
+| Expressions/TernaryExpression.ps1:1:8:1:22 | ...?...:... | Expressions/TernaryExpression.ps1:1:1:1:22 | ...=... |
+| Expressions/TernaryExpression.ps1:1:9:1:9 | 6 | Expressions/TernaryExpression.ps1:1:9:1:15 | ... -gt ... |
+| Expressions/TernaryExpression.ps1:1:9:1:15 | ... -gt ... | Expressions/TernaryExpression.ps1:1:8:1:16 | (...) |
+| Expressions/TernaryExpression.ps1:1:15:1:15 | 7 | Expressions/TernaryExpression.ps1:1:9:1:15 | ... -gt ... |
+| Expressions/TernaryExpression.ps1:1:20:1:20 | 1 | Expressions/TernaryExpression.ps1:1:8:1:22 | ...?...:... |
+| Expressions/TernaryExpression.ps1:1:22:1:22 | 2 | Expressions/TernaryExpression.ps1:1:8:1:22 | ...?...:... |
+| Loops/DoUntil.ps1:1:1:7:18 | do...until... | Loops/DoUntil.ps1:1:1:7:18 | {...} |
+| Loops/DoUntil.ps1:1:1:7:18 | {...} | Loops/DoUntil.ps1:1:1:7:18 | {...} |
+| Loops/DoUntil.ps1:1:1:7:18 | {...} | file://:0:0:0:0 | toplevel function for DoUntil.ps1 |
+| Loops/DoUntil.ps1:2:1:7:1 | {...} | Loops/DoUntil.ps1:1:1:7:18 | do...until... |
+| Loops/DoUntil.ps1:3:2:3:19 | Starting Loop $a | Loops/DoUntil.ps1:3:2:3:19 | [Stmt] Starting Loop $a |
+| Loops/DoUntil.ps1:3:2:3:19 | [Stmt] Starting Loop $a | Loops/DoUntil.ps1:2:1:7:1 | {...} |
+| Loops/DoUntil.ps1:4:2:4:3 | (no string representation) | Loops/DoUntil.ps1:2:1:7:1 | {...} |
+| Loops/DoUntil.ps1:5:2:5:5 | ...++ | Loops/DoUntil.ps1:5:2:5:5 | [Stmt] ...++ |
+| Loops/DoUntil.ps1:5:2:5:5 | [Stmt] ...++ | Loops/DoUntil.ps1:2:1:7:1 | {...} |
+| Loops/DoUntil.ps1:6:2:6:16 | Now $a is $a | Loops/DoUntil.ps1:6:2:6:16 | [Stmt] Now $a is $a |
+| Loops/DoUntil.ps1:6:2:6:16 | [Stmt] Now $a is $a | Loops/DoUntil.ps1:2:1:7:1 | {...} |
+| Loops/DoUntil.ps1:7:10:7:17 | ... -le ... | Loops/DoUntil.ps1:1:1:7:18 | do...until... |
+| Loops/DoUntil.ps1:7:17:7:17 | 5 | Loops/DoUntil.ps1:7:10:7:17 | ... -le ... |
+| Loops/DoWhile.ps1:1:1:7:18 | do...while... | Loops/DoWhile.ps1:1:1:7:18 | {...} |
+| Loops/DoWhile.ps1:1:1:7:18 | {...} | Loops/DoWhile.ps1:1:1:7:18 | {...} |
+| Loops/DoWhile.ps1:1:1:7:18 | {...} | file://:0:0:0:0 | toplevel function for DoWhile.ps1 |
+| Loops/DoWhile.ps1:2:1:7:1 | {...} | Loops/DoWhile.ps1:1:1:7:18 | do...while... |
+| Loops/DoWhile.ps1:3:2:3:19 | Starting Loop $a | Loops/DoWhile.ps1:3:2:3:19 | [Stmt] Starting Loop $a |
+| Loops/DoWhile.ps1:3:2:3:19 | [Stmt] Starting Loop $a | Loops/DoWhile.ps1:2:1:7:1 | {...} |
+| Loops/DoWhile.ps1:4:2:4:3 | (no string representation) | Loops/DoWhile.ps1:2:1:7:1 | {...} |
+| Loops/DoWhile.ps1:5:2:5:5 | ...++ | Loops/DoWhile.ps1:5:2:5:5 | [Stmt] ...++ |
+| Loops/DoWhile.ps1:5:2:5:5 | [Stmt] ...++ | Loops/DoWhile.ps1:2:1:7:1 | {...} |
+| Loops/DoWhile.ps1:6:2:6:16 | Now $a is $a | Loops/DoWhile.ps1:6:2:6:16 | [Stmt] Now $a is $a |
+| Loops/DoWhile.ps1:6:2:6:16 | [Stmt] Now $a is $a | Loops/DoWhile.ps1:2:1:7:1 | {...} |
+| Loops/DoWhile.ps1:7:10:7:17 | ... -le ... | Loops/DoWhile.ps1:1:1:7:18 | do...while... |
+| Loops/DoWhile.ps1:7:17:7:17 | 5 | Loops/DoWhile.ps1:7:10:7:17 | ... -le ... |
+| Loops/While.ps1:1:1:1:4 | var | Loops/While.ps1:1:1:1:8 | ...=... |
+| Loops/While.ps1:1:1:1:4 | var | Loops/While.ps1:1:1:13:1 | {...} |
+| Loops/While.ps1:1:1:1:8 | ...=... | Loops/While.ps1:1:1:13:1 | {...} |
+| Loops/While.ps1:1:1:13:1 | {...} | Loops/While.ps1:1:1:13:1 | {...} |
+| Loops/While.ps1:1:1:13:1 | {...} | file://:0:0:0:0 | toplevel function for While.ps1 |
+| Loops/While.ps1:1:8:1:8 | 1 | Loops/While.ps1:1:1:1:8 | ...=... |
+| Loops/While.ps1:2:1:13:1 | while(...) {...} | Loops/While.ps1:1:1:13:1 | {...} |
+| Loops/While.ps1:2:8:2:11 | var | Loops/While.ps1:2:8:2:17 | ... -le ... |
+| Loops/While.ps1:2:8:2:17 | ... -le ... | Loops/While.ps1:2:1:13:1 | while(...) {...} |
+| Loops/While.ps1:2:17:2:17 | 5 | Loops/While.ps1:2:8:2:17 | ... -le ... |
+| Loops/While.ps1:3:1:13:1 | {...} | Loops/While.ps1:2:1:13:1 | while(...) {...} |
+| Loops/While.ps1:4:5:4:14 | Write-Host | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:5:4:40 | Call to Write-Host | Loops/While.ps1:4:5:4:40 | [Stmt] Call to Write-Host |
+| Loops/While.ps1:4:5:4:40 | [Stmt] Call to Write-Host | Loops/While.ps1:3:1:13:1 | {...} |
+| Loops/While.ps1:4:16:4:18 | The | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:20:4:24 | value | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:26:4:27 | of | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:29:4:31 | Var | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:33:4:35 | is: | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:4:37:4:40 | var | Loops/While.ps1:4:5:4:40 | Call to Write-Host |
+| Loops/While.ps1:5:5:5:8 | var | Loops/While.ps1:5:5:5:10 | ...++ |
+| Loops/While.ps1:5:5:5:10 | ...++ | Loops/While.ps1:5:5:5:10 | [Stmt] ...++ |
+| Loops/While.ps1:5:5:5:10 | [Stmt] ...++ | Loops/While.ps1:3:1:13:1 | {...} |
+| Loops/While.ps1:6:5:12:5 | [Stmt] if (...) {...} else {...} | Loops/While.ps1:3:1:13:1 | {...} |
+| Loops/While.ps1:6:5:12:5 | if (...) {...} else {...} | Loops/While.ps1:6:5:12:5 | [Stmt] if (...) {...} else {...} |
+| Loops/While.ps1:6:9:6:12 | var | Loops/While.ps1:6:9:6:18 | ... -le ... |
+| Loops/While.ps1:6:9:6:18 | ... -le ... | Loops/While.ps1:6:5:12:5 | if (...) {...} else {...} |
+| Loops/While.ps1:6:18:6:18 | 3 | Loops/While.ps1:6:9:6:18 | ... -le ... |
+| Loops/While.ps1:6:20:8:5 | {...} | Loops/While.ps1:6:5:12:5 | if (...) {...} else {...} |
+| Loops/While.ps1:7:9:7:16 | continue | Loops/While.ps1:6:20:8:5 | {...} |
+| Loops/While.ps1:10:5:12:5 | {...} | Loops/While.ps1:6:5:12:5 | if (...) {...} else {...} |
+| Loops/While.ps1:11:9:11:13 | break | Loops/While.ps1:10:5:12:5 | {...} |
+| Redirections/FileRedirection.ps1:1:1:3:1 | $(...) | Redirections/FileRedirection.ps1:1:1:3:19 | [Stmt] $(...) |
+| Redirections/FileRedirection.ps1:1:1:3:19 | [Stmt] $(...) | Redirections/FileRedirection.ps1:1:1:3:19 | {...} |
+| Redirections/FileRedirection.ps1:1:1:3:19 | {...} | Redirections/FileRedirection.ps1:1:1:3:19 | {...} |
+| Redirections/FileRedirection.ps1:1:1:3:19 | {...} | file://:0:0:0:0 | toplevel function for FileRedirection.ps1 |
+| Redirections/FileRedirection.ps1:2:5:2:8 | Here | Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here |
+| Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here | Redirections/FileRedirection.ps1:2:5:2:31 | [Stmt] Call to Here |
+| Redirections/FileRedirection.ps1:2:5:2:31 | [Stmt] Call to Here | Redirections/FileRedirection.ps1:2:5:2:31 | {...} |
+| Redirections/FileRedirection.ps1:2:5:2:31 | {...} | Redirections/FileRedirection.ps1:1:1:3:1 | $(...) |
+| Redirections/FileRedirection.ps1:2:10:2:11 | is | Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here |
+| Redirections/FileRedirection.ps1:2:13:2:16 | your | Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here |
+| Redirections/FileRedirection.ps1:2:18:2:24 | current | Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here |
+| Redirections/FileRedirection.ps1:2:26:2:31 | script | Redirections/FileRedirection.ps1:2:5:2:31 | Call to Here |
+| Redirections/FileRedirection.ps1:3:10:3:19 | output.txt | Redirections/FileRedirection.ps1:3:8:3:19 | FileRedirection |
+| Statements/ExitStatement.ps1:1:1:1:7 | exit ... | Statements/ExitStatement.ps1:1:1:1:7 | {...} |
+| Statements/ExitStatement.ps1:1:1:1:7 | {...} | Statements/ExitStatement.ps1:1:1:1:7 | {...} |
+| Statements/ExitStatement.ps1:1:1:1:7 | {...} | file://:0:0:0:0 | toplevel function for ExitStatement.ps1 |
+| Statements/ExitStatement.ps1:1:6:1:7 | -1 | Statements/ExitStatement.ps1:1:1:1:7 | exit ... |
+| Statements/IfStatement.ps1:1:1:1:2 | x | Statements/IfStatement.ps1:1:1:1:6 | ...=... |
+| Statements/IfStatement.ps1:1:1:1:2 | x | Statements/IfStatement.ps1:1:1:8:1 | {...} |
+| Statements/IfStatement.ps1:1:1:1:6 | ...=... | Statements/IfStatement.ps1:1:1:8:1 | {...} |
+| Statements/IfStatement.ps1:1:1:8:1 | {...} | Statements/IfStatement.ps1:1:1:8:1 | {...} |
+| Statements/IfStatement.ps1:1:1:8:1 | {...} | file://:0:0:0:0 | toplevel function for IfStatement.ps1 |
+| Statements/IfStatement.ps1:1:6:1:6 | 4 | Statements/IfStatement.ps1:1:1:1:6 | ...=... |
+| Statements/IfStatement.ps1:3:1:8:1 | [Stmt] if (...) {...} else {...} | Statements/IfStatement.ps1:1:1:8:1 | {...} |
+| Statements/IfStatement.ps1:3:1:8:1 | if (...) {...} else {...} | Statements/IfStatement.ps1:3:1:8:1 | [Stmt] if (...) {...} else {...} |
+| Statements/IfStatement.ps1:3:5:3:6 | x | Statements/IfStatement.ps1:3:5:3:12 | ... -ge ... |
+| Statements/IfStatement.ps1:3:5:3:12 | ... -ge ... | Statements/IfStatement.ps1:3:1:8:1 | if (...) {...} else {...} |
+| Statements/IfStatement.ps1:3:12:3:12 | 3 | Statements/IfStatement.ps1:3:5:3:12 | ... -ge ... |
+| Statements/IfStatement.ps1:3:15:5:1 | {...} | Statements/IfStatement.ps1:3:1:8:1 | if (...) {...} else {...} |
+| Statements/IfStatement.ps1:4:2:4:35 | $x is greater than or equal to 3 | Statements/IfStatement.ps1:4:2:4:35 | [Stmt] $x is greater than or equal to 3 |
+| Statements/IfStatement.ps1:4:2:4:35 | [Stmt] $x is greater than or equal to 3 | Statements/IfStatement.ps1:3:15:5:1 | {...} |
+| Statements/IfStatement.ps1:4:3:4:4 | x | Statements/IfStatement.ps1:4:2:4:35 | $x is greater than or equal to 3 |
+| Statements/IfStatement.ps1:6:6:8:1 | {...} | Statements/IfStatement.ps1:3:1:8:1 | if (...) {...} else {...} |
+| Statements/IfStatement.ps1:7:2:7:20 | $x is less than 3 | Statements/IfStatement.ps1:7:2:7:20 | [Stmt] $x is less than 3 |
+| Statements/IfStatement.ps1:7:2:7:20 | [Stmt] $x is less than 3 | Statements/IfStatement.ps1:6:6:8:1 | {...} |
+| Statements/IfStatement.ps1:7:3:7:4 | x | Statements/IfStatement.ps1:7:2:7:20 | $x is less than 3 |
+| Statements/TrapStatement.ps1:1:1:4:1 | TrapTest | Statements/TrapStatement.ps1:1:1:4:1 | def of TrapTest |
+| Statements/TrapStatement.ps1:1:1:4:1 | def of TrapTest | Statements/TrapStatement.ps1:1:1:6:8 | {...} |
+| Statements/TrapStatement.ps1:1:1:6:8 | {...} | Statements/TrapStatement.ps1:1:1:6:8 | {...} |
+| Statements/TrapStatement.ps1:1:1:6:8 | {...} | file://:0:0:0:0 | toplevel function for TrapStatement.ps1 |
+| Statements/TrapStatement.ps1:1:19:4:1 | {...} | Statements/TrapStatement.ps1:1:1:4:1 | TrapTest |
+| Statements/TrapStatement.ps1:2:5:2:25 | trap {...} | Statements/TrapStatement.ps1:2:5:3:18 | {...} |
+| Statements/TrapStatement.ps1:2:5:3:18 | {...} | Statements/TrapStatement.ps1:1:19:4:1 | {...} |
+| Statements/TrapStatement.ps1:2:10:2:25 | {...} | Statements/TrapStatement.ps1:2:5:2:25 | trap {...} |
+| Statements/TrapStatement.ps1:2:11:2:24 | Error found. | Statements/TrapStatement.ps1:2:11:2:24 | [Stmt] Error found. |
+| Statements/TrapStatement.ps1:2:11:2:24 | [Stmt] Error found. | Statements/TrapStatement.ps1:2:10:2:25 | {...} |
+| Statements/TrapStatement.ps1:3:5:3:18 | Call to nonsenseString | Statements/TrapStatement.ps1:3:5:3:18 | [Stmt] Call to nonsenseString |
+| Statements/TrapStatement.ps1:3:5:3:18 | [Stmt] Call to nonsenseString | Statements/TrapStatement.ps1:2:5:3:18 | {...} |
+| Statements/TrapStatement.ps1:3:5:3:18 | nonsenseString | Statements/TrapStatement.ps1:3:5:3:18 | Call to nonsenseString |
+| Statements/TrapStatement.ps1:6:1:6:8 | Call to TrapTest | Statements/TrapStatement.ps1:6:1:6:8 | [Stmt] Call to TrapTest |
+| Statements/TrapStatement.ps1:6:1:6:8 | TrapTest | Statements/TrapStatement.ps1:6:1:6:8 | Call to TrapTest |
+| Statements/TrapStatement.ps1:6:1:6:8 | [Stmt] Call to TrapTest | Statements/TrapStatement.ps1:1:1:6:8 | {...} |
+| Statements/Try.ps1:1:1:13:1 | try {...} | Statements/Try.ps1:1:1:13:1 | {...} |
+| Statements/Try.ps1:1:1:13:1 | {...} | Statements/Try.ps1:1:1:13:1 | {...} |
+| Statements/Try.ps1:1:1:13:1 | {...} | file://:0:0:0:0 | toplevel function for Try.ps1 |
+| Statements/Try.ps1:1:5:4:1 | {...} | Statements/Try.ps1:1:1:13:1 | try {...} |
+| Statements/Try.ps1:2:4:2:13 | Exception | Statements/Try.ps1:1:1:13:1 | {...} |
+| Statements/Try.ps1:2:4:2:13 | Exception | Statements/Try.ps1:2:4:2:94 | ...=... |
+| Statements/Try.ps1:2:4:2:94 | ...=... | Statements/Try.ps1:1:5:4:1 | {...} |
+| Statements/Try.ps1:2:17:2:26 | New-Object | Statements/Try.ps1:2:17:2:94 | Call to New-Object |
+| Statements/Try.ps1:2:17:2:94 | Call to New-Object | Statements/Try.ps1:2:4:2:94 | ...=... |
+| Statements/Try.ps1:2:28:2:52 | System.Xaml.XamlException | Statements/Try.ps1:2:17:2:94 | Call to New-Object |
+| Statements/Try.ps1:2:68:2:94 | (...) | Statements/Try.ps1:2:17:2:94 | Call to New-Object |
+| Statements/Try.ps1:2:69:2:79 | Bad XAML! | Statements/Try.ps1:2:69:2:93 | ...,... |
+| Statements/Try.ps1:2:69:2:93 | ...,... | Statements/Try.ps1:2:68:2:94 | (...) |
+| Statements/Try.ps1:2:82:2:86 | null | Statements/Try.ps1:2:69:2:93 | ...,... |
+| Statements/Try.ps1:2:89:2:90 | 10 | Statements/Try.ps1:2:69:2:93 | ...,... |
+| Statements/Try.ps1:2:93:2:93 | 2 | Statements/Try.ps1:2:69:2:93 | ...,... |
+| Statements/Try.ps1:3:5:3:20 | throw ... | Statements/Try.ps1:1:5:4:1 | {...} |
+| Statements/Try.ps1:3:11:3:20 | Exception | Statements/Try.ps1:3:5:3:20 | throw ... |
+| Statements/Try.ps1:5:1:7:1 | catch[...] {...} | Statements/Try.ps1:1:1:13:1 | try {...} |
+| Statements/Try.ps1:5:7:5:31 | System.Net.WebException | Statements/Try.ps1:5:1:7:1 | catch[...] {...} |
+| Statements/Try.ps1:5:33:5:55 | System.IO.IOException | Statements/Try.ps1:5:1:7:1 | catch[...] {...} |
+| Statements/Try.ps1:5:57:7:1 | {...} | Statements/Try.ps1:5:1:7:1 | catch[...] {...} |
+| Statements/Try.ps1:6:5:6:63 | Unable to download MyDoc.doc from http://www.contoso.com. | Statements/Try.ps1:6:5:6:63 | [Stmt] Unable to download MyDoc.doc from http://www.contoso.com. |
+| Statements/Try.ps1:6:5:6:63 | [Stmt] Unable to download MyDoc.doc from http://www.contoso.com. | Statements/Try.ps1:5:57:7:1 | {...} |
+| Statements/Try.ps1:8:1:10:1 | catch {...} | Statements/Try.ps1:1:1:13:1 | try {...} |
+| Statements/Try.ps1:8:7:10:1 | {...} | Statements/Try.ps1:8:1:10:1 | catch {...} |
+| Statements/Try.ps1:9:5:9:51 | An error occurred that could not be resolved. | Statements/Try.ps1:9:5:9:51 | [Stmt] An error occurred that could not be resolved. |
+| Statements/Try.ps1:9:5:9:51 | [Stmt] An error occurred that could not be resolved. | Statements/Try.ps1:8:7:10:1 | {...} |
+| Statements/Try.ps1:11:9:13:1 | {...} | Statements/Try.ps1:1:1:13:1 | try {...} |
+| Statements/Try.ps1:12:5:12:36 | The finally block is executed. | Statements/Try.ps1:12:5:12:36 | [Stmt] The finally block is executed. |
+| Statements/Try.ps1:12:5:12:36 | [Stmt] The finally block is executed. | Statements/Try.ps1:11:9:13:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | Get-Number | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | def of Get-Number |
+| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | def of Get-Number | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | {...} | file://:0:0:0:0 | toplevel function for UseProcessBlockForPipelineCommand.ps1 |
+| Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | Number | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | [synth] pipeline | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:1:1:11:1 | Get-Number |
+| Statements/UseProcessBlockForPipelineCommand.ps1:3:5:3:21 | CmdletBinding | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:4:5:10:11 | {...} | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | {...} |
+| Statements/UseProcessBlockForPipelineCommand.ps1:5:9:5:38 | ValueFromPipeline | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | Number |
+| Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:36 | (no string representation) | Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:36 | ValueFromPipeline |
+| Statements/UseProcessBlockForPipelineCommand.ps1:5:20:5:36 | ValueFromPipeline | Statements/UseProcessBlockForPipelineCommand.ps1:5:9:5:38 | ValueFromPipeline |
+| Statements/UseProcessBlockForPipelineCommand.ps1:6:9:6:13 | int | Statements/UseProcessBlockForPipelineCommand.ps1:2:1:11:1 | Number |
+| Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:11 | Number | Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:11 | [Stmt] Number |
+| Statements/UseProcessBlockForPipelineCommand.ps1:10:5:10:11 | [Stmt] Number | Statements/UseProcessBlockForPipelineCommand.ps1:4:5:10:11 | {...} |
diff --git a/powershell/ql/test/library-tests/controlflow/graph/Cfg.expected b/powershell/ql/test/library-tests/controlflow/graph/Cfg.expected
index 65f28412b3a1..c2432f65b155 100644
--- a/powershell/ql/test/library-tests/controlflow/graph/Cfg.expected
+++ b/powershell/ql/test/library-tests/controlflow/graph/Cfg.expected
@@ -1,812 +1,759 @@
-| conditionals.ps1:1:1:9:2 | test-if | conditionals.ps1:11:1:22:2 | test-if-else | |
-| conditionals.ps1:1:1:129:2 | conditionals.ps1 | conditionals.ps1:1:1:129:2 | exit conditionals.ps1 (normal) | |
-| conditionals.ps1:1:1:129:2 | conditionals.ps1 | conditionals.ps1:1:1:129:2 | {...} | |
-| conditionals.ps1:1:1:129:2 | enter conditionals.ps1 | conditionals.ps1:1:1:129:2 | conditionals.ps1 | |
-| conditionals.ps1:1:1:129:2 | exit conditionals.ps1 (normal) | conditionals.ps1:1:1:129:2 | exit conditionals.ps1 | |
-| conditionals.ps1:1:1:129:2 | {...} | conditionals.ps1:1:1:9:2 | test-if | |
-| conditionals.ps1:1:18:9:2 | enter {...} | conditionals.ps1:1:18:9:2 | {...} | |
-| conditionals.ps1:1:18:9:2 | exit {...} (normal) | conditionals.ps1:1:18:9:2 | exit {...} | |
-| conditionals.ps1:1:18:9:2 | {...} | conditionals.ps1:2:5:2:19 | param(...) | |
-| conditionals.ps1:2:5:2:19 | param(...) | conditionals.ps1:2:5:8:14 | {...} | |
-| conditionals.ps1:2:5:8:14 | {...} | conditionals.ps1:4:5:7:6 | if (...) {...} | |
-| conditionals.ps1:4:5:7:6 | if (...) {...} | conditionals.ps1:4:8:4:15 | myBool | |
-| conditionals.ps1:4:8:4:15 | myBool | conditionals.ps1:4:8:4:15 | myBool | false, true |
-| conditionals.ps1:4:8:4:15 | myBool | conditionals.ps1:5:5:7:6 | {...} | true |
-| conditionals.ps1:5:5:7:6 | {...} | conditionals.ps1:6:9:6:18 | return ... | |
-| conditionals.ps1:6:9:6:18 | return ... | conditionals.ps1:6:16:6:18 | 10 | |
-| conditionals.ps1:6:16:6:18 | 10 | conditionals.ps1:6:16:6:18 | 10 | |
-| conditionals.ps1:6:16:6:18 | 10 | conditionals.ps1:8:5:8:14 | return ... | |
-| conditionals.ps1:8:5:8:14 | return ... | conditionals.ps1:8:12:8:14 | 11 | |
-| conditionals.ps1:8:12:8:14 | 11 | conditionals.ps1:1:18:9:2 | exit {...} (normal) | |
-| conditionals.ps1:8:12:8:14 | 11 | conditionals.ps1:8:12:8:14 | 11 | |
-| conditionals.ps1:11:1:22:2 | test-if-else | conditionals.ps1:24:1:32:2 | test-if-conj | |
-| conditionals.ps1:11:23:22:2 | enter {...} | conditionals.ps1:11:23:22:2 | {...} | |
-| conditionals.ps1:11:23:22:2 | exit {...} (normal) | conditionals.ps1:11:23:22:2 | exit {...} | |
-| conditionals.ps1:11:23:22:2 | {...} | conditionals.ps1:12:5:12:19 | param(...) | |
-| conditionals.ps1:12:5:12:19 | param(...) | conditionals.ps1:12:5:21:6 | {...} | |
-| conditionals.ps1:12:5:21:6 | {...} | conditionals.ps1:14:5:21:6 | if (...) {...} else {...} | |
-| conditionals.ps1:14:5:21:6 | if (...) {...} else {...} | conditionals.ps1:14:8:14:15 | myBool | |
-| conditionals.ps1:14:8:14:15 | myBool | conditionals.ps1:14:8:14:15 | myBool | false, true |
-| conditionals.ps1:14:8:14:15 | myBool | conditionals.ps1:15:5:17:6 | {...} | true |
-| conditionals.ps1:14:8:14:15 | myBool | conditionals.ps1:19:5:21:6 | {...} | false |
-| conditionals.ps1:15:5:17:6 | {...} | conditionals.ps1:16:9:16:18 | return ... | |
-| conditionals.ps1:16:9:16:18 | return ... | conditionals.ps1:16:16:16:18 | 10 | |
-| conditionals.ps1:16:16:16:18 | 10 | conditionals.ps1:11:23:22:2 | exit {...} (normal) | |
-| conditionals.ps1:16:16:16:18 | 10 | conditionals.ps1:16:16:16:18 | 10 | |
-| conditionals.ps1:19:5:21:6 | {...} | conditionals.ps1:20:9:20:18 | return ... | |
-| conditionals.ps1:20:9:20:18 | return ... | conditionals.ps1:20:16:20:18 | 11 | |
-| conditionals.ps1:20:16:20:18 | 11 | conditionals.ps1:11:23:22:2 | exit {...} (normal) | |
-| conditionals.ps1:20:16:20:18 | 11 | conditionals.ps1:20:16:20:18 | 11 | |
-| conditionals.ps1:24:1:32:2 | test-if-conj | conditionals.ps1:34:1:45:2 | test-if-else-conj | |
-| conditionals.ps1:24:23:32:2 | enter {...} | conditionals.ps1:24:23:32:2 | {...} | |
-| conditionals.ps1:24:23:32:2 | exit {...} (normal) | conditionals.ps1:24:23:32:2 | exit {...} | |
-| conditionals.ps1:24:23:32:2 | {...} | conditionals.ps1:25:5:25:30 | param(...) | |
-| conditionals.ps1:25:5:25:30 | param(...) | conditionals.ps1:25:5:31:14 | {...} | |
-| conditionals.ps1:25:5:31:14 | {...} | conditionals.ps1:27:5:30:6 | if (...) {...} | |
-| conditionals.ps1:27:5:30:6 | if (...) {...} | conditionals.ps1:27:8:27:16 | myBool1 | |
-| conditionals.ps1:27:8:27:16 | myBool1 | conditionals.ps1:27:22:27:30 | myBool2 | false, true |
-| conditionals.ps1:27:8:27:30 | ... -and ... | conditionals.ps1:28:5:30:6 | {...} | true |
-| conditionals.ps1:27:8:27:30 | [false] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | false |
-| conditionals.ps1:27:8:27:30 | [true] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | true |
-| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [false] ... -and ... | false |
-| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [true] ... -and ... | true |
-| conditionals.ps1:28:5:30:6 | {...} | conditionals.ps1:29:9:29:18 | return ... | |
-| conditionals.ps1:29:9:29:18 | return ... | conditionals.ps1:29:16:29:18 | 10 | |
-| conditionals.ps1:29:16:29:18 | 10 | conditionals.ps1:29:16:29:18 | 10 | |
-| conditionals.ps1:29:16:29:18 | 10 | conditionals.ps1:31:5:31:14 | return ... | |
-| conditionals.ps1:31:5:31:14 | return ... | conditionals.ps1:31:12:31:14 | 11 | |
-| conditionals.ps1:31:12:31:14 | 11 | conditionals.ps1:24:23:32:2 | exit {...} (normal) | |
-| conditionals.ps1:31:12:31:14 | 11 | conditionals.ps1:31:12:31:14 | 11 | |
-| conditionals.ps1:34:1:45:2 | test-if-else-conj | conditionals.ps1:47:1:55:2 | test-if-disj | |
-| conditionals.ps1:34:28:45:2 | enter {...} | conditionals.ps1:34:28:45:2 | {...} | |
-| conditionals.ps1:34:28:45:2 | exit {...} (normal) | conditionals.ps1:34:28:45:2 | exit {...} | |
-| conditionals.ps1:34:28:45:2 | {...} | conditionals.ps1:35:5:35:30 | param(...) | |
-| conditionals.ps1:35:5:35:30 | param(...) | conditionals.ps1:35:5:44:6 | {...} | |
-| conditionals.ps1:35:5:44:6 | {...} | conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | |
-| conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | conditionals.ps1:37:8:37:16 | myBool1 | |
-| conditionals.ps1:37:8:37:16 | myBool1 | conditionals.ps1:37:22:37:30 | myBool2 | false, true |
-| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:38:5:40:6 | {...} | true |
-| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:42:5:44:6 | {...} | false |
-| conditionals.ps1:37:8:37:30 | [false] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | false |
-| conditionals.ps1:37:8:37:30 | [true] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | true |
-| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [false] ... -and ... | false |
-| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [true] ... -and ... | true |
-| conditionals.ps1:38:5:40:6 | {...} | conditionals.ps1:39:9:39:18 | return ... | |
-| conditionals.ps1:39:9:39:18 | return ... | conditionals.ps1:39:16:39:18 | 10 | |
-| conditionals.ps1:39:16:39:18 | 10 | conditionals.ps1:34:28:45:2 | exit {...} (normal) | |
-| conditionals.ps1:39:16:39:18 | 10 | conditionals.ps1:39:16:39:18 | 10 | |
-| conditionals.ps1:42:5:44:6 | {...} | conditionals.ps1:43:9:43:18 | return ... | |
-| conditionals.ps1:43:9:43:18 | return ... | conditionals.ps1:43:16:43:18 | 11 | |
-| conditionals.ps1:43:16:43:18 | 11 | conditionals.ps1:34:28:45:2 | exit {...} (normal) | |
-| conditionals.ps1:43:16:43:18 | 11 | conditionals.ps1:43:16:43:18 | 11 | |
-| conditionals.ps1:47:1:55:2 | test-if-disj | conditionals.ps1:57:1:68:2 | test-if-else-disj | |
-| conditionals.ps1:47:23:55:2 | enter {...} | conditionals.ps1:47:23:55:2 | {...} | |
-| conditionals.ps1:47:23:55:2 | exit {...} (normal) | conditionals.ps1:47:23:55:2 | exit {...} | |
-| conditionals.ps1:47:23:55:2 | {...} | conditionals.ps1:48:5:48:30 | param(...) | |
-| conditionals.ps1:48:5:48:30 | param(...) | conditionals.ps1:48:5:54:14 | {...} | |
-| conditionals.ps1:48:5:54:14 | {...} | conditionals.ps1:50:5:53:6 | if (...) {...} | |
-| conditionals.ps1:50:5:53:6 | if (...) {...} | conditionals.ps1:50:8:50:16 | myBool1 | |
-| conditionals.ps1:50:8:50:16 | myBool1 | conditionals.ps1:50:21:50:29 | myBool2 | false, true |
-| conditionals.ps1:50:8:50:29 | ... -or ... | conditionals.ps1:51:5:53:6 | {...} | true |
-| conditionals.ps1:50:8:50:29 | [false] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | false |
-| conditionals.ps1:50:8:50:29 | [true] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | true |
-| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [false] ... -or ... | false |
-| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [true] ... -or ... | true |
-| conditionals.ps1:51:5:53:6 | {...} | conditionals.ps1:52:9:52:18 | return ... | |
-| conditionals.ps1:52:9:52:18 | return ... | conditionals.ps1:52:16:52:18 | 10 | |
-| conditionals.ps1:52:16:52:18 | 10 | conditionals.ps1:52:16:52:18 | 10 | |
-| conditionals.ps1:52:16:52:18 | 10 | conditionals.ps1:54:5:54:14 | return ... | |
-| conditionals.ps1:54:5:54:14 | return ... | conditionals.ps1:54:12:54:14 | 11 | |
-| conditionals.ps1:54:12:54:14 | 11 | conditionals.ps1:47:23:55:2 | exit {...} (normal) | |
-| conditionals.ps1:54:12:54:14 | 11 | conditionals.ps1:54:12:54:14 | 11 | |
-| conditionals.ps1:57:1:68:2 | test-if-else-disj | conditionals.ps1:70:1:82:2 | test-else-if | |
-| conditionals.ps1:57:28:68:2 | enter {...} | conditionals.ps1:57:28:68:2 | {...} | |
-| conditionals.ps1:57:28:68:2 | exit {...} (normal) | conditionals.ps1:57:28:68:2 | exit {...} | |
-| conditionals.ps1:57:28:68:2 | {...} | conditionals.ps1:58:5:58:30 | param(...) | |
-| conditionals.ps1:58:5:58:30 | param(...) | conditionals.ps1:58:5:67:6 | {...} | |
-| conditionals.ps1:58:5:67:6 | {...} | conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | |
-| conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | conditionals.ps1:60:8:60:16 | myBool1 | |
-| conditionals.ps1:60:8:60:16 | myBool1 | conditionals.ps1:60:21:60:29 | myBool2 | false, true |
-| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:61:5:63:6 | {...} | true |
-| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:65:5:67:6 | {...} | false |
-| conditionals.ps1:60:8:60:29 | [false] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | false |
-| conditionals.ps1:60:8:60:29 | [true] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | true |
-| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [false] ... -or ... | false |
-| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [true] ... -or ... | true |
-| conditionals.ps1:61:5:63:6 | {...} | conditionals.ps1:62:9:62:18 | return ... | |
-| conditionals.ps1:62:9:62:18 | return ... | conditionals.ps1:62:16:62:18 | 10 | |
-| conditionals.ps1:62:16:62:18 | 10 | conditionals.ps1:57:28:68:2 | exit {...} (normal) | |
-| conditionals.ps1:62:16:62:18 | 10 | conditionals.ps1:62:16:62:18 | 10 | |
-| conditionals.ps1:65:5:67:6 | {...} | conditionals.ps1:66:9:66:18 | return ... | |
-| conditionals.ps1:66:9:66:18 | return ... | conditionals.ps1:66:16:66:18 | 11 | |
-| conditionals.ps1:66:16:66:18 | 11 | conditionals.ps1:57:28:68:2 | exit {...} (normal) | |
-| conditionals.ps1:66:16:66:18 | 11 | conditionals.ps1:66:16:66:18 | 11 | |
-| conditionals.ps1:70:1:82:2 | test-else-if | conditionals.ps1:84:1:99:2 | test-else-if-else | |
-| conditionals.ps1:70:23:82:2 | enter {...} | conditionals.ps1:70:23:82:2 | {...} | |
-| conditionals.ps1:70:23:82:2 | exit {...} (normal) | conditionals.ps1:70:23:82:2 | exit {...} | |
-| conditionals.ps1:70:23:82:2 | {...} | conditionals.ps1:71:5:71:30 | param(...) | |
-| conditionals.ps1:71:5:71:30 | param(...) | conditionals.ps1:71:5:81:14 | {...} | |
-| conditionals.ps1:71:5:81:14 | {...} | conditionals.ps1:73:5:80:6 | if (...) {...} | |
-| conditionals.ps1:73:5:80:6 | if (...) {...} | conditionals.ps1:73:8:73:16 | myBool1 | |
-| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:73:8:73:16 | myBool1 | false, true |
-| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:74:5:76:6 | {...} | true |
-| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:77:12:77:19 | myBoo2 | false |
-| conditionals.ps1:74:5:76:6 | {...} | conditionals.ps1:75:9:75:18 | return ... | |
-| conditionals.ps1:75:9:75:18 | return ... | conditionals.ps1:75:16:75:18 | 10 | |
-| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:75:16:75:18 | 10 | |
-| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:81:5:81:14 | return ... | |
-| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:77:12:77:19 | myBoo2 | false, true |
-| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:78:5:80:6 | {...} | true |
-| conditionals.ps1:78:5:80:6 | {...} | conditionals.ps1:79:9:79:18 | return ... | |
-| conditionals.ps1:79:9:79:18 | return ... | conditionals.ps1:79:16:79:18 | 11 | |
-| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:79:16:79:18 | 11 | |
-| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:81:5:81:14 | return ... | |
-| conditionals.ps1:81:5:81:14 | return ... | conditionals.ps1:81:12:81:14 | 12 | |
-| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:70:23:82:2 | exit {...} (normal) | |
-| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:81:12:81:14 | 12 | |
-| conditionals.ps1:84:1:99:2 | test-else-if-else | conditionals.ps1:101:1:108:2 | test-switch | |
-| conditionals.ps1:84:28:99:2 | enter {...} | conditionals.ps1:84:28:99:2 | {...} | |
-| conditionals.ps1:84:28:99:2 | exit {...} (normal) | conditionals.ps1:84:28:99:2 | exit {...} | |
-| conditionals.ps1:84:28:99:2 | {...} | conditionals.ps1:85:5:85:30 | param(...) | |
-| conditionals.ps1:85:5:85:30 | param(...) | conditionals.ps1:85:5:98:6 | {...} | |
-| conditionals.ps1:85:5:98:6 | {...} | conditionals.ps1:87:5:98:6 | if (...) {...} else {...} | |
-| conditionals.ps1:87:5:98:6 | if (...) {...} else {...} | conditionals.ps1:87:8:87:16 | myBool1 | |
-| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:87:8:87:16 | myBool1 | false, true |
-| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:88:5:90:6 | {...} | true |
-| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:91:12:91:19 | myBoo2 | false |
-| conditionals.ps1:88:5:90:6 | {...} | conditionals.ps1:89:9:89:18 | return ... | |
-| conditionals.ps1:89:9:89:18 | return ... | conditionals.ps1:89:16:89:18 | 10 | |
-| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
-| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:89:16:89:18 | 10 | |
-| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:91:12:91:19 | myBoo2 | false, true |
-| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:92:5:94:6 | {...} | true |
-| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:96:5:98:6 | {...} | false |
-| conditionals.ps1:92:5:94:6 | {...} | conditionals.ps1:93:9:93:18 | return ... | |
-| conditionals.ps1:93:9:93:18 | return ... | conditionals.ps1:93:16:93:18 | 11 | |
-| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
-| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:93:16:93:18 | 11 | |
-| conditionals.ps1:96:5:98:6 | {...} | conditionals.ps1:97:9:97:18 | return ... | |
-| conditionals.ps1:97:9:97:18 | return ... | conditionals.ps1:97:16:97:18 | 12 | |
-| conditionals.ps1:97:16:97:18 | 12 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
-| conditionals.ps1:97:16:97:18 | 12 | conditionals.ps1:97:16:97:18 | 12 | |
-| conditionals.ps1:101:1:108:2 | test-switch | conditionals.ps1:110:1:121:2 | test-switch-default | |
-| conditionals.ps1:101:26:108:2 | enter {...} | conditionals.ps1:101:26:108:2 | {...} | |
-| conditionals.ps1:101:26:108:2 | exit {...} (normal) | conditionals.ps1:101:26:108:2 | exit {...} | |
-| conditionals.ps1:101:26:108:2 | {...} | conditionals.ps1:102:5:107:6 | {...} | |
-| conditionals.ps1:102:5:107:6 | switch(...) {...} | conditionals.ps1:102:12:102:14 | n | |
-| conditionals.ps1:102:5:107:6 | {...} | conditionals.ps1:102:5:107:6 | switch(...) {...} | |
-| conditionals.ps1:102:12:102:14 | n | conditionals.ps1:102:12:102:14 | n | |
-| conditionals.ps1:102:12:102:14 | n | conditionals.ps1:104:9:104:11 | 0: | |
-| conditionals.ps1:104:9:104:11 | 0: | conditionals.ps1:104:12:104:25 | {...} | true |
-| conditionals.ps1:104:9:104:11 | 0: | conditionals.ps1:105:9:105:11 | 1: | false |
-| conditionals.ps1:104:12:104:25 | {...} | conditionals.ps1:104:14:104:22 | return ... | |
-| conditionals.ps1:104:14:104:22 | return ... | conditionals.ps1:104:21:104:22 | 0 | |
-| conditionals.ps1:104:21:104:22 | 0 | conditionals.ps1:101:26:108:2 | exit {...} (normal) | |
-| conditionals.ps1:104:21:104:22 | 0 | conditionals.ps1:104:21:104:22 | 0 | |
-| conditionals.ps1:105:9:105:11 | 1: | conditionals.ps1:105:12:105:25 | {...} | true |
-| conditionals.ps1:105:9:105:11 | 1: | conditionals.ps1:106:9:106:11 | 2: | false |
-| conditionals.ps1:105:12:105:25 | {...} | conditionals.ps1:105:14:105:22 | return ... | |
-| conditionals.ps1:105:14:105:22 | return ... | conditionals.ps1:105:21:105:22 | 1 | |
-| conditionals.ps1:105:21:105:22 | 1 | conditionals.ps1:101:26:108:2 | exit {...} (normal) | |
-| conditionals.ps1:105:21:105:22 | 1 | conditionals.ps1:105:21:105:22 | 1 | |
-| conditionals.ps1:106:9:106:11 | 2: | conditionals.ps1:101:26:108:2 | exit {...} (normal) | false |
-| conditionals.ps1:106:9:106:11 | 2: | conditionals.ps1:106:12:106:25 | {...} | true |
-| conditionals.ps1:106:12:106:25 | {...} | conditionals.ps1:106:14:106:22 | return ... | |
-| conditionals.ps1:106:14:106:22 | return ... | conditionals.ps1:106:21:106:22 | 2 | |
-| conditionals.ps1:106:21:106:22 | 2 | conditionals.ps1:101:26:108:2 | exit {...} (normal) | |
-| conditionals.ps1:106:21:106:22 | 2 | conditionals.ps1:106:21:106:22 | 2 | |
-| conditionals.ps1:110:1:121:2 | test-switch-default | conditionals.ps1:123:1:129:2 | test-switch-assign | |
-| conditionals.ps1:110:34:121:2 | enter {...} | conditionals.ps1:110:34:121:2 | {...} | |
-| conditionals.ps1:110:34:121:2 | exit {...} (normal) | conditionals.ps1:110:34:121:2 | exit {...} | |
-| conditionals.ps1:110:34:121:2 | {...} | conditionals.ps1:111:5:120:6 | {...} | |
-| conditionals.ps1:111:5:120:6 | switch(...) {...} | conditionals.ps1:111:12:111:14 | n | |
-| conditionals.ps1:111:5:120:6 | {...} | conditionals.ps1:111:5:120:6 | switch(...) {...} | |
-| conditionals.ps1:111:12:111:14 | n | conditionals.ps1:111:12:111:14 | n | |
-| conditionals.ps1:111:12:111:14 | n | conditionals.ps1:113:9:113:11 | 0: | |
-| conditionals.ps1:113:9:113:11 | 0: | conditionals.ps1:113:12:113:25 | {...} | true |
-| conditionals.ps1:113:9:113:11 | 0: | conditionals.ps1:114:9:114:11 | 1: | false |
-| conditionals.ps1:113:12:113:25 | {...} | conditionals.ps1:113:14:113:22 | return ... | |
-| conditionals.ps1:113:14:113:22 | return ... | conditionals.ps1:113:21:113:22 | 0 | |
-| conditionals.ps1:113:21:113:22 | 0 | conditionals.ps1:110:34:121:2 | exit {...} (normal) | |
-| conditionals.ps1:113:21:113:22 | 0 | conditionals.ps1:113:21:113:22 | 0 | |
-| conditionals.ps1:114:9:114:11 | 1: | conditionals.ps1:114:12:114:25 | {...} | true |
-| conditionals.ps1:114:9:114:11 | 1: | conditionals.ps1:115:9:115:11 | 2: | false |
-| conditionals.ps1:114:12:114:25 | {...} | conditionals.ps1:114:14:114:22 | return ... | |
-| conditionals.ps1:114:14:114:22 | return ... | conditionals.ps1:114:21:114:22 | 1 | |
-| conditionals.ps1:114:21:114:22 | 1 | conditionals.ps1:110:34:121:2 | exit {...} (normal) | |
-| conditionals.ps1:114:21:114:22 | 1 | conditionals.ps1:114:21:114:22 | 1 | |
-| conditionals.ps1:115:9:115:11 | 2: | conditionals.ps1:115:12:115:25 | {...} | true |
-| conditionals.ps1:115:9:115:11 | 2: | conditionals.ps1:116:9:116:17 | default: | false |
-| conditionals.ps1:115:12:115:25 | {...} | conditionals.ps1:115:14:115:22 | return ... | |
-| conditionals.ps1:115:14:115:22 | return ... | conditionals.ps1:115:21:115:22 | 2 | |
-| conditionals.ps1:115:21:115:22 | 2 | conditionals.ps1:110:34:121:2 | exit {...} (normal) | |
-| conditionals.ps1:115:21:115:22 | 2 | conditionals.ps1:115:21:115:22 | 2 | |
-| conditionals.ps1:116:9:116:17 | default: | conditionals.ps1:110:34:121:2 | exit {...} (normal) | false |
-| conditionals.ps1:116:9:116:17 | default: | conditionals.ps1:116:18:119:10 | {...} | true |
-| conditionals.ps1:116:18:119:10 | {...} | conditionals.ps1:117:13:117:25 | Write-Output | |
-| conditionals.ps1:117:13:117:25 | Write-Output | conditionals.ps1:117:26:117:34 | Error! | |
-| conditionals.ps1:117:13:117:34 | call to Write-Output | conditionals.ps1:118:13:118:21 | return ... | |
-| conditionals.ps1:117:26:117:34 | Error! | conditionals.ps1:117:13:117:34 | call to Write-Output | |
-| conditionals.ps1:118:13:118:21 | return ... | conditionals.ps1:118:20:118:21 | 3 | |
-| conditionals.ps1:118:20:118:21 | 3 | conditionals.ps1:110:34:121:2 | exit {...} (normal) | |
-| conditionals.ps1:118:20:118:21 | 3 | conditionals.ps1:118:20:118:21 | 3 | |
-| conditionals.ps1:123:1:129:2 | test-switch-assign | conditionals.ps1:1:1:129:2 | exit conditionals.ps1 (normal) | |
-| conditionals.ps1:123:33:129:2 | enter {...} | conditionals.ps1:123:33:129:2 | {...} | |
-| conditionals.ps1:123:33:129:2 | exit {...} (normal) | conditionals.ps1:123:33:129:2 | exit {...} | |
-| conditionals.ps1:123:33:129:2 | {...} | conditionals.ps1:124:5:128:6 | {...} | |
-| conditionals.ps1:124:5:124:7 | a | conditionals.ps1:124:10:128:6 | switch(...) {...} | |
-| conditionals.ps1:124:5:128:6 | ...=... | conditionals.ps1:124:5:124:7 | a | |
-| conditionals.ps1:124:5:128:6 | {...} | conditionals.ps1:124:5:128:6 | ...=... | |
-| conditionals.ps1:124:10:128:6 | switch(...) {...} | conditionals.ps1:124:17:124:19 | n | |
-| conditionals.ps1:124:17:124:19 | n | conditionals.ps1:124:17:124:19 | n | |
-| conditionals.ps1:124:17:124:19 | n | conditionals.ps1:125:9:125:11 | 0: | |
-| conditionals.ps1:125:9:125:11 | 0: | conditionals.ps1:125:12:125:19 | {...} | true |
-| conditionals.ps1:125:9:125:11 | 0: | conditionals.ps1:126:9:126:11 | 1: | false |
-| conditionals.ps1:125:12:125:19 | {...} | conditionals.ps1:125:14:125:17 | 0 | |
-| conditionals.ps1:125:14:125:17 | 0 | conditionals.ps1:123:33:129:2 | exit {...} (normal) | |
-| conditionals.ps1:125:14:125:17 | 0 | conditionals.ps1:125:14:125:17 | 0 | |
-| conditionals.ps1:126:9:126:11 | 1: | conditionals.ps1:126:12:126:19 | {...} | true |
-| conditionals.ps1:126:9:126:11 | 1: | conditionals.ps1:127:9:127:11 | 2: | false |
-| conditionals.ps1:126:12:126:19 | {...} | conditionals.ps1:126:14:126:17 | 1 | |
-| conditionals.ps1:126:14:126:17 | 1 | conditionals.ps1:123:33:129:2 | exit {...} (normal) | |
-| conditionals.ps1:126:14:126:17 | 1 | conditionals.ps1:126:14:126:17 | 1 | |
-| conditionals.ps1:127:9:127:11 | 2: | conditionals.ps1:123:33:129:2 | exit {...} (normal) | false |
-| conditionals.ps1:127:9:127:11 | 2: | conditionals.ps1:127:12:127:19 | {...} | true |
-| conditionals.ps1:127:12:127:19 | {...} | conditionals.ps1:127:14:127:17 | 2 | |
-| conditionals.ps1:127:14:127:17 | 2 | conditionals.ps1:123:33:129:2 | exit {...} (normal) | |
-| conditionals.ps1:127:14:127:17 | 2 | conditionals.ps1:127:14:127:17 | 2 | |
-| functions.ps1:1:1:9:2 | Add-Numbers-Arguments | functions.ps1:11:1:11:29 | foo | |
-| functions.ps1:1:1:52:2 | {...} | functions.ps1:1:1:9:2 | Add-Numbers-Arguments | |
-| functions.ps1:1:1:54:1 | enter functions.ps1 | functions.ps1:1:1:54:1 | functions.ps1 | |
-| functions.ps1:1:1:54:1 | exit functions.ps1 (normal) | functions.ps1:1:1:54:1 | exit functions.ps1 | |
-| functions.ps1:1:1:54:1 | functions.ps1 | functions.ps1:1:1:52:2 | {...} | |
-| functions.ps1:1:1:54:1 | functions.ps1 | functions.ps1:1:1:54:1 | exit functions.ps1 (normal) | |
-| functions.ps1:1:32:9:2 | enter {...} | functions.ps1:1:32:9:2 | {...} | |
-| functions.ps1:1:32:9:2 | exit {...} (normal) | functions.ps1:1:32:9:2 | exit {...} | |
-| functions.ps1:1:32:9:2 | {...} | functions.ps1:3:5:6:6 | param(...) | |
-| functions.ps1:3:5:6:6 | param(...) | functions.ps1:3:5:8:24 | {...} | |
-| functions.ps1:3:5:8:24 | {...} | functions.ps1:8:5:8:13 | number1 | |
-| functions.ps1:8:5:8:13 | number1 | functions.ps1:8:16:8:24 | number2 | |
-| functions.ps1:8:5:8:24 | ...+... | functions.ps1:1:32:9:2 | exit {...} (normal) | |
-| functions.ps1:8:5:8:24 | ...+... | functions.ps1:8:5:8:24 | ...+... | |
-| functions.ps1:8:16:8:24 | number2 | functions.ps1:8:5:8:24 | ...+... | |
-| functions.ps1:11:1:11:29 | foo | functions.ps1:13:1:20:2 | Default-Arguments | |
-| functions.ps1:11:16:11:29 | enter {...} | functions.ps1:11:16:11:29 | {...} | |
-| functions.ps1:11:16:11:29 | exit {...} (normal) | functions.ps1:11:16:11:29 | exit {...} | |
-| functions.ps1:11:16:11:29 | {...} | functions.ps1:11:18:11:27 | param(...) | |
-| functions.ps1:11:18:11:27 | param(...) | functions.ps1:11:18:11:27 | {...} | |
-| functions.ps1:11:18:11:27 | {...} | functions.ps1:11:16:11:29 | exit {...} (normal) | |
-| functions.ps1:13:1:20:2 | Default-Arguments | functions.ps1:22:1:34:2 | Add-Numbers-From-Array | |
-| functions.ps1:13:28:20:2 | enter {...} | functions.ps1:13:28:20:2 | {...} | |
-| functions.ps1:13:28:20:2 | exit {...} (normal) | functions.ps1:13:28:20:2 | exit {...} | |
-| functions.ps1:13:28:20:2 | {...} | functions.ps1:16:24:16:25 | 0 | |
-| functions.ps1:14:5:18:6 | param(...) | functions.ps1:14:5:19:19 | {...} | |
-| functions.ps1:14:5:19:19 | {...} | functions.ps1:19:5:19:10 | name | |
-| functions.ps1:16:24:16:25 | 0 | functions.ps1:17:24:17:30 | name1 | |
-| functions.ps1:17:24:17:30 | name1 | functions.ps1:17:33:17:34 | 1 | |
-| functions.ps1:17:24:17:34 | ...+... | functions.ps1:14:5:18:6 | param(...) | |
-| functions.ps1:17:33:17:34 | 1 | functions.ps1:17:24:17:34 | ...+... | |
-| functions.ps1:19:5:19:10 | name | functions.ps1:19:13:19:19 | name2 | |
-| functions.ps1:19:5:19:19 | ...+... | functions.ps1:13:28:20:2 | exit {...} (normal) | |
-| functions.ps1:19:5:19:19 | ...+... | functions.ps1:19:5:19:19 | ...+... | |
-| functions.ps1:19:13:19:19 | name2 | functions.ps1:19:5:19:19 | ...+... | |
-| functions.ps1:22:1:34:2 | Add-Numbers-From-Array | functions.ps1:36:1:52:2 | Add-Numbers-From-Pipeline | |
-| functions.ps1:22:33:34:2 | enter {...} | functions.ps1:22:33:34:2 | {...} | |
-| functions.ps1:22:33:34:2 | exit {...} (normal) | functions.ps1:22:33:34:2 | exit {...} | |
-| functions.ps1:22:33:34:2 | {...} | functions.ps1:24:5:26:6 | param(...) | |
-| functions.ps1:24:5:26:6 | param(...) | functions.ps1:24:5:33:9 | {...} | |
-| functions.ps1:24:5:33:9 | {...} | functions.ps1:28:5:28:13 | ...=... | |
-| functions.ps1:28:5:28:9 | sum | functions.ps1:28:12:28:13 | 0 | |
-| functions.ps1:28:5:28:13 | ...=... | functions.ps1:28:5:28:9 | sum | |
-| functions.ps1:28:12:28:13 | 0 | functions.ps1:28:12:28:13 | 0 | |
-| functions.ps1:28:12:28:13 | 0 | functions.ps1:29:25:29:33 | numbers | |
-| functions.ps1:29:5:32:6 | forach(... in ...) | functions.ps1:29:14:29:21 | number | non-empty |
-| functions.ps1:29:5:32:6 | forach(... in ...) | functions.ps1:33:5:33:9 | sum | empty |
-| functions.ps1:29:14:29:21 | number | functions.ps1:29:35:32:6 | {...} | |
-| functions.ps1:29:25:29:33 | numbers | functions.ps1:29:5:32:6 | forach(... in ...) | |
-| functions.ps1:29:25:29:33 | numbers | functions.ps1:29:25:29:33 | numbers | |
-| functions.ps1:29:35:32:6 | {...} | functions.ps1:31:9:31:24 | ...=... | |
-| functions.ps1:31:9:31:13 | sum | functions.ps1:31:17:31:24 | number | |
-| functions.ps1:31:9:31:24 | ...=... | functions.ps1:31:9:31:13 | sum | |
-| functions.ps1:31:17:31:24 | number | functions.ps1:29:5:32:6 | forach(... in ...) | |
-| functions.ps1:31:17:31:24 | number | functions.ps1:31:17:31:24 | number | |
-| functions.ps1:33:5:33:9 | sum | functions.ps1:22:33:34:2 | exit {...} (normal) | |
-| functions.ps1:33:5:33:9 | sum | functions.ps1:33:5:33:9 | sum | |
-| functions.ps1:36:1:52:2 | Add-Numbers-From-Pipeline | functions.ps1:1:1:54:1 | exit functions.ps1 (normal) | |
-| functions.ps1:36:36:52:2 | enter {...} | functions.ps1:36:36:52:2 | {...} | |
-| functions.ps1:36:36:52:2 | exit {...} (normal) | functions.ps1:36:36:52:2 | exit {...} | |
-| functions.ps1:36:36:52:2 | {...} | functions.ps1:38:5:40:6 | param(...) | |
-| functions.ps1:38:5:40:6 | param(...) | functions.ps1:41:5:43:6 | {...} | |
-| functions.ps1:41:5:43:6 | {...} | functions.ps1:42:9:42:17 | ...=... | |
-| functions.ps1:42:9:42:13 | sum | functions.ps1:42:16:42:17 | 0 | |
-| functions.ps1:42:9:42:17 | ...=... | functions.ps1:42:9:42:13 | sum | |
-| functions.ps1:42:16:42:17 | 0 | functions.ps1:42:16:42:17 | 0 | |
-| functions.ps1:42:16:42:17 | 0 | functions.ps1:44:5:47:6 | {...} | |
-| functions.ps1:44:5:47:6 | {...} | functions.ps1:46:9:46:19 | ...=... | |
-| functions.ps1:46:9:46:13 | sum | functions.ps1:46:17:46:19 | _ | |
-| functions.ps1:46:9:46:19 | ...=... | functions.ps1:46:9:46:13 | sum | |
-| functions.ps1:46:17:46:19 | _ | functions.ps1:44:5:47:6 | {...} | |
-| functions.ps1:46:17:46:19 | _ | functions.ps1:46:17:46:19 | _ | |
-| functions.ps1:46:17:46:19 | _ | functions.ps1:48:5:51:6 | {...} | |
-| functions.ps1:48:5:51:6 | {...} | functions.ps1:50:9:50:13 | sum | |
-| functions.ps1:50:9:50:13 | sum | functions.ps1:36:36:52:2 | exit {...} (normal) | |
-| functions.ps1:50:9:50:13 | sum | functions.ps1:50:9:50:13 | sum | |
-| global.ps1:1:1:4:2 | {...} | global.ps1:2:5:2:11 | ...=... | |
-| global.ps1:1:1:7:2 | enter global.ps1 | global.ps1:1:1:7:2 | global.ps1 | |
-| global.ps1:1:1:7:2 | exit global.ps1 (normal) | global.ps1:1:1:7:2 | exit global.ps1 | |
-| global.ps1:1:1:7:2 | global.ps1 | global.ps1:1:1:4:2 | {...} | |
-| global.ps1:1:1:7:2 | global.ps1 | global.ps1:1:1:7:2 | exit global.ps1 (normal) | |
-| global.ps1:2:5:2:7 | a | global.ps1:2:10:2:11 | 1 | |
-| global.ps1:2:5:2:11 | ...=... | global.ps1:2:5:2:7 | a | |
-| global.ps1:2:10:2:11 | 1 | global.ps1:2:10:2:11 | 1 | |
-| global.ps1:2:10:2:11 | 1 | global.ps1:3:5:3:11 | ...=... | |
-| global.ps1:3:5:3:7 | b | global.ps1:3:10:3:11 | 2 | |
-| global.ps1:3:5:3:11 | ...=... | global.ps1:3:5:3:7 | b | |
-| global.ps1:3:10:3:11 | 2 | global.ps1:3:10:3:11 | 2 | |
-| global.ps1:3:10:3:11 | 2 | global.ps1:5:1:7:2 | {...} | |
-| global.ps1:5:1:7:2 | {...} | global.ps1:6:5:6:17 | ...=... | |
-| global.ps1:6:5:6:7 | c | global.ps1:6:10:6:12 | a | |
-| global.ps1:6:5:6:17 | ...=... | global.ps1:6:5:6:7 | c | |
-| global.ps1:6:10:6:12 | a | global.ps1:6:15:6:17 | b | |
-| global.ps1:6:10:6:17 | ...+... | global.ps1:1:1:7:2 | exit global.ps1 (normal) | |
-| global.ps1:6:10:6:17 | ...+... | global.ps1:6:10:6:17 | ...+... | |
-| global.ps1:6:15:6:17 | b | global.ps1:6:10:6:17 | ...+... | |
-| loops.ps1:1:1:7:2 | Test-While | loops.ps1:9:1:15:2 | Test-Break | |
-| loops.ps1:1:1:68:2 | {...} | loops.ps1:1:1:7:2 | Test-While | |
-| loops.ps1:1:1:70:1 | enter loops.ps1 | loops.ps1:1:1:70:1 | loops.ps1 | |
-| loops.ps1:1:1:70:1 | exit loops.ps1 (normal) | loops.ps1:1:1:70:1 | exit loops.ps1 | |
-| loops.ps1:1:1:70:1 | loops.ps1 | loops.ps1:1:1:68:2 | {...} | |
-| loops.ps1:1:1:70:1 | loops.ps1 | loops.ps1:1:1:70:1 | exit loops.ps1 (normal) | |
-| loops.ps1:1:21:7:2 | enter {...} | loops.ps1:1:21:7:2 | {...} | |
-| loops.ps1:1:21:7:2 | exit {...} (normal) | loops.ps1:1:21:7:2 | exit {...} | |
-| loops.ps1:1:21:7:2 | {...} | loops.ps1:2:5:6:6 | {...} | |
-| loops.ps1:2:5:2:7 | a | loops.ps1:2:10:2:11 | 0 | |
-| loops.ps1:2:5:2:11 | ...=... | loops.ps1:2:5:2:7 | a | |
-| loops.ps1:2:5:6:6 | {...} | loops.ps1:2:5:2:11 | ...=... | |
-| loops.ps1:2:10:2:11 | 0 | loops.ps1:2:10:2:11 | 0 | |
-| loops.ps1:2:10:2:11 | 0 | loops.ps1:4:5:6:6 | while(...) {...} | |
-| loops.ps1:4:5:6:6 | while(...) {...} | loops.ps1:4:11:4:13 | a | |
-| loops.ps1:4:11:4:13 | a | loops.ps1:4:18:4:20 | 10 | |
-| loops.ps1:4:11:4:20 | ... -le ... | loops.ps1:1:21:7:2 | exit {...} (normal) | false |
-| loops.ps1:4:11:4:20 | ... -le ... | loops.ps1:4:11:4:20 | ... -le ... | false, true |
-| loops.ps1:4:11:4:20 | ... -le ... | loops.ps1:4:22:6:6 | {...} | true |
-| loops.ps1:4:18:4:20 | 10 | loops.ps1:4:11:4:20 | ... -le ... | |
-| loops.ps1:4:22:6:6 | {...} | loops.ps1:5:9:5:20 | ...=... | |
-| loops.ps1:5:9:5:11 | a | loops.ps1:5:14:5:16 | a | |
-| loops.ps1:5:9:5:20 | ...=... | loops.ps1:5:9:5:11 | a | |
-| loops.ps1:5:14:5:16 | a | loops.ps1:5:19:5:20 | 1 | |
-| loops.ps1:5:14:5:20 | ...+... | loops.ps1:4:11:4:13 | a | |
-| loops.ps1:5:14:5:20 | ...+... | loops.ps1:5:14:5:20 | ...+... | |
-| loops.ps1:5:19:5:20 | 1 | loops.ps1:5:14:5:20 | ...+... | |
-| loops.ps1:9:1:15:2 | Test-Break | loops.ps1:17:1:23:2 | Test-Continue | |
-| loops.ps1:9:21:15:2 | enter {...} | loops.ps1:9:21:15:2 | {...} | |
-| loops.ps1:9:21:15:2 | exit {...} (normal) | loops.ps1:9:21:15:2 | exit {...} | |
-| loops.ps1:9:21:15:2 | {...} | loops.ps1:10:5:14:6 | {...} | |
-| loops.ps1:10:5:10:7 | a | loops.ps1:10:10:10:11 | 0 | |
-| loops.ps1:10:5:10:11 | ...=... | loops.ps1:10:5:10:7 | a | |
-| loops.ps1:10:5:14:6 | {...} | loops.ps1:10:5:10:11 | ...=... | |
-| loops.ps1:10:10:10:11 | 0 | loops.ps1:10:10:10:11 | 0 | |
-| loops.ps1:10:10:10:11 | 0 | loops.ps1:11:5:14:6 | while(...) {...} | |
-| loops.ps1:11:5:14:6 | while(...) {...} | loops.ps1:11:11:11:13 | a | |
-| loops.ps1:11:11:11:13 | a | loops.ps1:11:18:11:20 | 10 | |
-| loops.ps1:11:11:11:20 | ... -le ... | loops.ps1:9:21:15:2 | exit {...} (normal) | false |
-| loops.ps1:11:11:11:20 | ... -le ... | loops.ps1:11:11:11:20 | ... -le ... | false, true |
-| loops.ps1:11:11:11:20 | ... -le ... | loops.ps1:11:22:14:6 | {...} | true |
-| loops.ps1:11:18:11:20 | 10 | loops.ps1:11:11:11:20 | ... -le ... | |
-| loops.ps1:11:22:14:6 | {...} | loops.ps1:12:9:12:14 | break | |
-| loops.ps1:12:9:12:14 | break | loops.ps1:9:21:15:2 | exit {...} (normal) | break |
-| loops.ps1:17:1:23:2 | Test-Continue | loops.ps1:25:1:31:2 | Test-DoWhile | |
-| loops.ps1:17:24:23:2 | enter {...} | loops.ps1:17:24:23:2 | {...} | |
-| loops.ps1:17:24:23:2 | exit {...} (normal) | loops.ps1:17:24:23:2 | exit {...} | |
-| loops.ps1:17:24:23:2 | {...} | loops.ps1:18:5:22:6 | {...} | |
-| loops.ps1:18:5:18:7 | a | loops.ps1:18:10:18:11 | 0 | |
-| loops.ps1:18:5:18:11 | ...=... | loops.ps1:18:5:18:7 | a | |
-| loops.ps1:18:5:22:6 | {...} | loops.ps1:18:5:18:11 | ...=... | |
-| loops.ps1:18:10:18:11 | 0 | loops.ps1:18:10:18:11 | 0 | |
-| loops.ps1:18:10:18:11 | 0 | loops.ps1:19:5:22:6 | while(...) {...} | |
-| loops.ps1:19:5:22:6 | while(...) {...} | loops.ps1:19:11:19:13 | a | |
-| loops.ps1:19:11:19:13 | a | loops.ps1:19:18:19:20 | 10 | |
-| loops.ps1:19:11:19:20 | ... -le ... | loops.ps1:17:24:23:2 | exit {...} (normal) | false |
-| loops.ps1:19:11:19:20 | ... -le ... | loops.ps1:19:11:19:20 | ... -le ... | false, true |
-| loops.ps1:19:11:19:20 | ... -le ... | loops.ps1:19:22:22:6 | {...} | true |
-| loops.ps1:19:18:19:20 | 10 | loops.ps1:19:11:19:20 | ... -le ... | |
-| loops.ps1:19:22:22:6 | {...} | loops.ps1:20:9:20:17 | continue | |
-| loops.ps1:20:9:20:17 | continue | loops.ps1:19:11:19:13 | a | continue |
-| loops.ps1:25:1:31:2 | Test-DoWhile | loops.ps1:33:1:39:2 | Test-DoUntil | |
-| loops.ps1:25:23:31:2 | enter {...} | loops.ps1:25:23:31:2 | {...} | |
-| loops.ps1:25:23:31:2 | exit {...} (normal) | loops.ps1:25:23:31:2 | exit {...} | |
-| loops.ps1:25:23:31:2 | {...} | loops.ps1:26:5:30:24 | {...} | |
-| loops.ps1:26:5:26:7 | a | loops.ps1:26:10:26:11 | 0 | |
-| loops.ps1:26:5:26:11 | ...=... | loops.ps1:26:5:26:7 | a | |
-| loops.ps1:26:5:30:24 | {...} | loops.ps1:26:5:26:11 | ...=... | |
-| loops.ps1:26:10:26:11 | 0 | loops.ps1:26:10:26:11 | 0 | |
-| loops.ps1:26:10:26:11 | 0 | loops.ps1:28:5:30:24 | DoWhile | |
-| loops.ps1:28:5:30:24 | DoWhile | loops.ps1:28:8:30:6 | {...} | |
-| loops.ps1:28:8:30:6 | {...} | loops.ps1:29:9:29:20 | ...=... | |
-| loops.ps1:29:9:29:11 | a | loops.ps1:29:14:29:16 | a | |
-| loops.ps1:29:9:29:20 | ...=... | loops.ps1:29:9:29:11 | a | |
-| loops.ps1:29:14:29:16 | a | loops.ps1:29:19:29:20 | 1 | |
-| loops.ps1:29:14:29:20 | ...+... | loops.ps1:29:14:29:20 | ...+... | |
-| loops.ps1:29:14:29:20 | ...+... | loops.ps1:30:14:30:16 | a | |
-| loops.ps1:29:19:29:20 | 1 | loops.ps1:29:14:29:20 | ...+... | |
-| loops.ps1:30:14:30:16 | a | loops.ps1:30:21:30:23 | 10 | |
-| loops.ps1:30:14:30:23 | ... -le ... | loops.ps1:25:23:31:2 | exit {...} (normal) | false |
-| loops.ps1:30:14:30:23 | ... -le ... | loops.ps1:28:8:30:6 | {...} | true |
-| loops.ps1:30:14:30:23 | ... -le ... | loops.ps1:30:14:30:23 | ... -le ... | false, true |
-| loops.ps1:30:21:30:23 | 10 | loops.ps1:30:14:30:23 | ... -le ... | |
-| loops.ps1:33:1:39:2 | Test-DoUntil | loops.ps1:41:1:47:2 | Test-For | |
-| loops.ps1:33:23:39:2 | enter {...} | loops.ps1:33:23:39:2 | {...} | |
-| loops.ps1:33:23:39:2 | exit {...} (normal) | loops.ps1:33:23:39:2 | exit {...} | |
-| loops.ps1:33:23:39:2 | {...} | loops.ps1:34:5:38:24 | {...} | |
-| loops.ps1:34:5:34:7 | a | loops.ps1:34:10:34:11 | 0 | |
-| loops.ps1:34:5:34:11 | ...=... | loops.ps1:34:5:34:7 | a | |
-| loops.ps1:34:5:38:24 | {...} | loops.ps1:34:5:34:11 | ...=... | |
-| loops.ps1:34:10:34:11 | 0 | loops.ps1:34:10:34:11 | 0 | |
-| loops.ps1:34:10:34:11 | 0 | loops.ps1:36:5:38:24 | DoUntil | |
-| loops.ps1:36:5:38:24 | DoUntil | loops.ps1:36:8:38:6 | {...} | |
-| loops.ps1:36:8:38:6 | {...} | loops.ps1:37:9:37:20 | ...=... | |
-| loops.ps1:37:9:37:11 | a | loops.ps1:37:14:37:16 | a | |
-| loops.ps1:37:9:37:20 | ...=... | loops.ps1:37:9:37:11 | a | |
-| loops.ps1:37:14:37:16 | a | loops.ps1:37:19:37:20 | 1 | |
-| loops.ps1:37:14:37:20 | ...+... | loops.ps1:37:14:37:20 | ...+... | |
-| loops.ps1:37:14:37:20 | ...+... | loops.ps1:38:14:38:16 | a | |
-| loops.ps1:37:19:37:20 | 1 | loops.ps1:37:14:37:20 | ...+... | |
-| loops.ps1:38:14:38:16 | a | loops.ps1:38:21:38:23 | 10 | |
-| loops.ps1:38:14:38:23 | ... -ge ... | loops.ps1:33:23:39:2 | exit {...} (normal) | true |
-| loops.ps1:38:14:38:23 | ... -ge ... | loops.ps1:36:8:38:6 | {...} | false |
-| loops.ps1:38:14:38:23 | ... -ge ... | loops.ps1:38:14:38:23 | ... -ge ... | false, true |
-| loops.ps1:38:21:38:23 | 10 | loops.ps1:38:14:38:23 | ... -ge ... | |
-| loops.ps1:41:1:47:2 | Test-For | loops.ps1:49:1:56:2 | Test-ForEach | |
-| loops.ps1:41:19:47:2 | enter {...} | loops.ps1:41:19:47:2 | {...} | |
-| loops.ps1:41:19:47:2 | exit {...} (normal) | loops.ps1:41:19:47:2 | exit {...} | |
-| loops.ps1:41:19:47:2 | {...} | loops.ps1:42:5:46:6 | {...} | |
-| loops.ps1:42:5:42:7 | a | loops.ps1:42:10:42:11 | 0 | |
-| loops.ps1:42:5:42:11 | ...=... | loops.ps1:42:5:42:7 | a | |
-| loops.ps1:42:5:46:6 | {...} | loops.ps1:42:5:42:11 | ...=... | |
-| loops.ps1:42:10:42:11 | 0 | loops.ps1:42:10:42:11 | 0 | |
-| loops.ps1:42:10:42:11 | 0 | loops.ps1:44:5:46:6 | for(...;...;...) | |
-| loops.ps1:44:5:46:6 | for(...;...;...) | loops.ps1:44:10:44:16 | ...=... | |
-| loops.ps1:44:10:44:12 | i | loops.ps1:44:15:44:16 | 0 | |
-| loops.ps1:44:10:44:16 | ...=... | loops.ps1:44:10:44:12 | i | |
-| loops.ps1:44:15:44:16 | 0 | loops.ps1:44:15:44:16 | 0 | |
-| loops.ps1:44:15:44:16 | 0 | loops.ps1:44:18:44:20 | i | |
-| loops.ps1:44:18:44:20 | i | loops.ps1:44:25:44:27 | 10 | |
-| loops.ps1:44:18:44:27 | ... -le ... | loops.ps1:41:19:47:2 | exit {...} (normal) | false |
-| loops.ps1:44:18:44:27 | ... -le ... | loops.ps1:44:18:44:27 | ... -le ... | false, true |
-| loops.ps1:44:18:44:27 | ... -le ... | loops.ps1:44:42:46:6 | {...} | true |
-| loops.ps1:44:25:44:27 | 10 | loops.ps1:44:18:44:27 | ... -le ... | |
-| loops.ps1:44:29:44:31 | i | loops.ps1:44:34:44:36 | i | |
-| loops.ps1:44:29:44:40 | ...=... | loops.ps1:44:29:44:31 | i | |
-| loops.ps1:44:34:44:36 | i | loops.ps1:44:39:44:40 | 1 | |
-| loops.ps1:44:34:44:40 | ...+... | loops.ps1:44:18:44:20 | i | |
-| loops.ps1:44:34:44:40 | ...+... | loops.ps1:44:34:44:40 | ...+... | |
-| loops.ps1:44:39:44:40 | 1 | loops.ps1:44:34:44:40 | ...+... | |
-| loops.ps1:44:42:46:6 | {...} | loops.ps1:45:9:45:20 | ...=... | |
-| loops.ps1:45:9:45:11 | a | loops.ps1:45:14:45:16 | a | |
-| loops.ps1:45:9:45:20 | ...=... | loops.ps1:45:9:45:11 | a | |
-| loops.ps1:45:14:45:16 | a | loops.ps1:45:19:45:20 | 1 | |
-| loops.ps1:45:14:45:20 | ...+... | loops.ps1:44:18:44:20 | i | |
-| loops.ps1:45:14:45:20 | ...+... | loops.ps1:44:29:44:40 | ...=... | |
-| loops.ps1:45:14:45:20 | ...+... | loops.ps1:45:14:45:20 | ...+... | |
-| loops.ps1:45:19:45:20 | 1 | loops.ps1:45:14:45:20 | ...+... | |
-| loops.ps1:49:1:56:2 | Test-ForEach | loops.ps1:58:1:68:2 | Test-For-Ever | |
-| loops.ps1:49:23:56:2 | enter {...} | loops.ps1:49:23:56:2 | {...} | |
-| loops.ps1:49:23:56:2 | exit {...} (normal) | loops.ps1:49:23:56:2 | exit {...} | |
-| loops.ps1:49:23:56:2 | {...} | loops.ps1:50:5:55:6 | {...} | |
-| loops.ps1:50:5:50:17 | letterArray | loops.ps1:50:20:50:23 | a | |
-| loops.ps1:50:5:50:35 | ...=... | loops.ps1:50:5:50:17 | letterArray | |
-| loops.ps1:50:5:55:6 | {...} | loops.ps1:50:5:50:35 | ...=... | |
-| loops.ps1:50:20:50:23 | a | loops.ps1:50:24:50:27 | b | |
-| loops.ps1:50:20:50:35 | ...,... | loops.ps1:50:20:50:35 | ...,... | |
-| loops.ps1:50:20:50:35 | ...,... | loops.ps1:51:5:51:11 | ...=... | |
-| loops.ps1:50:24:50:27 | b | loops.ps1:50:28:50:31 | c | |
-| loops.ps1:50:28:50:31 | c | loops.ps1:50:32:50:35 | d | |
-| loops.ps1:50:32:50:35 | d | loops.ps1:50:20:50:35 | ...,... | |
-| loops.ps1:51:5:51:7 | a | loops.ps1:51:10:51:11 | 0 | |
-| loops.ps1:51:5:51:11 | ...=... | loops.ps1:51:5:51:7 | a | |
-| loops.ps1:51:10:51:11 | 0 | loops.ps1:51:10:51:11 | 0 | |
-| loops.ps1:51:10:51:11 | 0 | loops.ps1:52:25:52:37 | letterArray | |
-| loops.ps1:52:5:55:6 | forach(... in ...) | loops.ps1:49:23:56:2 | exit {...} (normal) | empty |
-| loops.ps1:52:5:55:6 | forach(... in ...) | loops.ps1:52:14:52:21 | letter | non-empty |
-| loops.ps1:52:14:52:21 | letter | loops.ps1:53:5:55:6 | {...} | |
-| loops.ps1:52:25:52:37 | letterArray | loops.ps1:52:5:55:6 | forach(... in ...) | |
-| loops.ps1:52:25:52:37 | letterArray | loops.ps1:52:25:52:37 | letterArray | |
-| loops.ps1:53:5:55:6 | {...} | loops.ps1:54:9:54:20 | ...=... | |
-| loops.ps1:54:9:54:11 | a | loops.ps1:54:14:54:16 | a | |
-| loops.ps1:54:9:54:20 | ...=... | loops.ps1:54:9:54:11 | a | |
-| loops.ps1:54:14:54:16 | a | loops.ps1:54:19:54:20 | 1 | |
-| loops.ps1:54:14:54:20 | ...+... | loops.ps1:52:5:55:6 | forach(... in ...) | |
-| loops.ps1:54:14:54:20 | ...+... | loops.ps1:54:14:54:20 | ...+... | |
-| loops.ps1:54:19:54:20 | 1 | loops.ps1:54:14:54:20 | ...+... | |
-| loops.ps1:58:1:68:2 | Test-For-Ever | loops.ps1:1:1:70:1 | exit loops.ps1 (normal) | |
-| loops.ps1:58:24:68:2 | enter {...} | loops.ps1:58:24:68:2 | {...} | |
-| loops.ps1:58:24:68:2 | exit {...} (normal) | loops.ps1:58:24:68:2 | exit {...} | |
-| loops.ps1:58:24:68:2 | {...} | loops.ps1:59:5:67:6 | {...} | |
-| loops.ps1:59:5:59:7 | a | loops.ps1:59:10:59:11 | 0 | |
-| loops.ps1:59:5:59:11 | ...=... | loops.ps1:59:5:59:7 | a | |
-| loops.ps1:59:5:67:6 | {...} | loops.ps1:59:5:59:11 | ...=... | |
-| loops.ps1:59:10:59:11 | 0 | loops.ps1:59:10:59:11 | 0 | |
-| loops.ps1:59:10:59:11 | 0 | loops.ps1:61:5:67:6 | for(...;...;...) | |
-| loops.ps1:61:5:67:6 | for(...;...;...) | loops.ps1:62:5:67:6 | {...} | |
-| loops.ps1:62:5:67:6 | {...} | loops.ps1:63:9:66:10 | if (...) {...} | |
-| loops.ps1:63:9:66:10 | if (...) {...} | loops.ps1:63:12:63:14 | a | |
-| loops.ps1:63:12:63:14 | a | loops.ps1:63:19:63:21 | 10 | |
-| loops.ps1:63:12:63:21 | ... -le ... | loops.ps1:63:12:63:21 | ... -le ... | false, true |
-| loops.ps1:63:12:63:21 | ... -le ... | loops.ps1:64:9:66:10 | {...} | true |
-| loops.ps1:63:19:63:21 | 10 | loops.ps1:63:12:63:21 | ... -le ... | |
-| loops.ps1:64:9:66:10 | {...} | loops.ps1:65:13:65:18 | break | |
-| loops.ps1:65:13:65:18 | break | loops.ps1:58:24:68:2 | exit {...} (normal) | break |
-| try.ps1:1:1:8:2 | test-try-catch | try.ps1:10:1:19:2 | test-try-with-throw-catch | |
-| try.ps1:1:1:194:2 | enter try.ps1 | try.ps1:1:1:194:2 | try.ps1 | |
-| try.ps1:1:1:194:2 | exit try.ps1 (normal) | try.ps1:1:1:194:2 | exit try.ps1 | |
-| try.ps1:1:1:194:2 | try.ps1 | try.ps1:1:1:194:2 | exit try.ps1 (normal) | |
-| try.ps1:1:1:194:2 | try.ps1 | try.ps1:1:1:194:2 | {...} | |
-| try.ps1:1:1:194:2 | {...} | try.ps1:1:1:8:2 | test-try-catch | |
-| try.ps1:1:25:8:2 | enter {...} | try.ps1:1:25:8:2 | {...} | |
-| try.ps1:1:25:8:2 | exit {...} (normal) | try.ps1:1:25:8:2 | exit {...} | |
-| try.ps1:1:25:8:2 | {...} | try.ps1:2:5:7:13 | {...} | |
-| try.ps1:2:5:6:6 | try {...} | try.ps1:2:9:4:6 | {...} | |
-| try.ps1:2:5:7:13 | {...} | try.ps1:2:5:6:6 | try {...} | |
-| try.ps1:2:9:4:6 | {...} | try.ps1:3:9:3:21 | Write-Output | |
-| try.ps1:3:9:3:21 | Write-Output | try.ps1:3:22:3:30 | Hello! | |
-| try.ps1:3:9:3:30 | call to Write-Output | try.ps1:7:5:7:13 | return ... | |
-| try.ps1:3:22:3:30 | Hello! | try.ps1:3:9:3:30 | call to Write-Output | |
-| try.ps1:7:5:7:13 | return ... | try.ps1:7:12:7:13 | 1 | |
-| try.ps1:7:12:7:13 | 1 | try.ps1:1:25:8:2 | exit {...} (normal) | |
-| try.ps1:7:12:7:13 | 1 | try.ps1:7:12:7:13 | 1 | |
-| try.ps1:10:1:19:2 | test-try-with-throw-catch | try.ps1:21:1:30:2 | test-try-with-throw-catch-with-throw | |
-| try.ps1:10:40:19:2 | enter {...} | try.ps1:10:40:19:2 | {...} | |
-| try.ps1:10:40:19:2 | exit {...} (normal) | try.ps1:10:40:19:2 | exit {...} | |
-| try.ps1:10:40:19:2 | {...} | try.ps1:11:5:18:13 | {...} | |
-| try.ps1:11:5:17:6 | try {...} | try.ps1:11:9:15:6 | {...} | |
-| try.ps1:11:5:18:13 | {...} | try.ps1:11:5:17:6 | try {...} | |
-| try.ps1:11:9:15:6 | {...} | try.ps1:12:9:14:10 | if (...) {...} | |
-| try.ps1:12:9:14:10 | if (...) {...} | try.ps1:12:12:12:14 | b | |
-| try.ps1:12:12:12:14 | b | try.ps1:12:12:12:14 | b | false, true |
-| try.ps1:12:12:12:14 | b | try.ps1:12:16:14:10 | {...} | true |
-| try.ps1:12:16:14:10 | {...} | try.ps1:13:13:13:21 | throw ... | |
-| try.ps1:13:13:13:21 | throw ... | try.ps1:13:19:13:21 | 42 | |
-| try.ps1:13:19:13:21 | 42 | try.ps1:13:19:13:21 | 42 | |
-| try.ps1:13:19:13:21 | 42 | try.ps1:18:5:18:13 | return ... | |
-| try.ps1:18:5:18:13 | return ... | try.ps1:18:12:18:13 | 1 | |
-| try.ps1:18:12:18:13 | 1 | try.ps1:10:40:19:2 | exit {...} (normal) | |
-| try.ps1:18:12:18:13 | 1 | try.ps1:18:12:18:13 | 1 | |
-| try.ps1:21:1:30:2 | test-try-with-throw-catch-with-throw | try.ps1:32:1:41:2 | test-try-with-throw-catch-with-rethrow | |
-| try.ps1:21:51:30:2 | enter {...} | try.ps1:21:51:30:2 | {...} | |
-| try.ps1:21:51:30:2 | exit {...} (normal) | try.ps1:21:51:30:2 | exit {...} | |
-| try.ps1:21:51:30:2 | {...} | try.ps1:22:5:29:13 | {...} | |
-| try.ps1:22:5:28:6 | try {...} | try.ps1:22:9:26:6 | {...} | |
-| try.ps1:22:5:29:13 | {...} | try.ps1:22:5:28:6 | try {...} | |
-| try.ps1:22:9:26:6 | {...} | try.ps1:23:9:25:10 | if (...) {...} | |
-| try.ps1:23:9:25:10 | if (...) {...} | try.ps1:23:12:23:14 | b | |
-| try.ps1:23:12:23:14 | b | try.ps1:23:12:23:14 | b | false, true |
-| try.ps1:23:12:23:14 | b | try.ps1:23:16:25:10 | {...} | true |
-| try.ps1:23:16:25:10 | {...} | try.ps1:24:13:24:21 | throw ... | |
-| try.ps1:24:13:24:21 | throw ... | try.ps1:24:19:24:21 | 42 | |
-| try.ps1:24:19:24:21 | 42 | try.ps1:24:19:24:21 | 42 | |
-| try.ps1:24:19:24:21 | 42 | try.ps1:29:5:29:13 | return ... | |
-| try.ps1:29:5:29:13 | return ... | try.ps1:29:12:29:13 | 1 | |
-| try.ps1:29:12:29:13 | 1 | try.ps1:21:51:30:2 | exit {...} (normal) | |
-| try.ps1:29:12:29:13 | 1 | try.ps1:29:12:29:13 | 1 | |
-| try.ps1:32:1:41:2 | test-try-with-throw-catch-with-rethrow | try.ps1:43:1:50:2 | test-try-catch-specific-1 | |
-| try.ps1:32:53:41:2 | enter {...} | try.ps1:32:53:41:2 | {...} | |
-| try.ps1:32:53:41:2 | exit {...} (normal) | try.ps1:32:53:41:2 | exit {...} | |
-| try.ps1:32:53:41:2 | {...} | try.ps1:33:5:40:13 | {...} | |
-| try.ps1:33:5:39:6 | try {...} | try.ps1:33:9:37:6 | {...} | |
-| try.ps1:33:5:40:13 | {...} | try.ps1:33:5:39:6 | try {...} | |
-| try.ps1:33:9:37:6 | {...} | try.ps1:34:9:36:10 | if (...) {...} | |
-| try.ps1:34:9:36:10 | if (...) {...} | try.ps1:34:12:34:14 | b | |
-| try.ps1:34:12:34:14 | b | try.ps1:34:12:34:14 | b | false, true |
-| try.ps1:34:12:34:14 | b | try.ps1:34:16:36:10 | {...} | true |
-| try.ps1:34:16:36:10 | {...} | try.ps1:35:13:35:21 | throw ... | |
-| try.ps1:35:13:35:21 | throw ... | try.ps1:35:19:35:21 | 42 | |
-| try.ps1:35:19:35:21 | 42 | try.ps1:35:19:35:21 | 42 | |
-| try.ps1:35:19:35:21 | 42 | try.ps1:40:5:40:13 | return ... | |
-| try.ps1:40:5:40:13 | return ... | try.ps1:40:12:40:13 | 1 | |
-| try.ps1:40:12:40:13 | 1 | try.ps1:32:53:41:2 | exit {...} (normal) | |
-| try.ps1:40:12:40:13 | 1 | try.ps1:40:12:40:13 | 1 | |
-| try.ps1:43:1:50:2 | test-try-catch-specific-1 | try.ps1:52:1:59:2 | test-try-catch-specific-1 | |
-| try.ps1:43:36:50:2 | enter {...} | try.ps1:43:36:50:2 | {...} | |
-| try.ps1:43:36:50:2 | exit {...} (normal) | try.ps1:43:36:50:2 | exit {...} | |
-| try.ps1:43:36:50:2 | {...} | try.ps1:44:5:49:13 | {...} | |
-| try.ps1:44:5:48:6 | try {...} | try.ps1:44:9:46:6 | {...} | |
-| try.ps1:44:5:49:13 | {...} | try.ps1:44:5:48:6 | try {...} | |
-| try.ps1:44:9:46:6 | {...} | try.ps1:45:9:45:21 | Write-Output | |
-| try.ps1:45:9:45:21 | Write-Output | try.ps1:45:22:45:30 | Hello! | |
-| try.ps1:45:9:45:30 | call to Write-Output | try.ps1:49:5:49:13 | return ... | |
-| try.ps1:45:22:45:30 | Hello! | try.ps1:45:9:45:30 | call to Write-Output | |
-| try.ps1:49:5:49:13 | return ... | try.ps1:49:12:49:13 | 1 | |
-| try.ps1:49:12:49:13 | 1 | try.ps1:43:36:50:2 | exit {...} (normal) | |
-| try.ps1:49:12:49:13 | 1 | try.ps1:49:12:49:13 | 1 | |
-| try.ps1:52:1:59:2 | test-try-catch-specific-1 | try.ps1:61:1:70:2 | test-try-two-catch-specific-1 | |
-| try.ps1:52:36:59:2 | enter {...} | try.ps1:52:36:59:2 | {...} | |
-| try.ps1:52:36:59:2 | exit {...} (normal) | try.ps1:52:36:59:2 | exit {...} | |
-| try.ps1:52:36:59:2 | {...} | try.ps1:53:5:58:13 | {...} | |
-| try.ps1:53:5:57:6 | try {...} | try.ps1:53:9:55:6 | {...} | |
-| try.ps1:53:5:58:13 | {...} | try.ps1:53:5:57:6 | try {...} | |
-| try.ps1:53:9:55:6 | {...} | try.ps1:54:9:54:21 | Write-Output | |
-| try.ps1:54:9:54:21 | Write-Output | try.ps1:54:22:54:30 | Hello! | |
-| try.ps1:54:9:54:30 | call to Write-Output | try.ps1:58:5:58:13 | return ... | |
-| try.ps1:54:22:54:30 | Hello! | try.ps1:54:9:54:30 | call to Write-Output | |
-| try.ps1:58:5:58:13 | return ... | try.ps1:58:12:58:13 | 1 | |
-| try.ps1:58:12:58:13 | 1 | try.ps1:52:36:59:2 | exit {...} (normal) | |
-| try.ps1:58:12:58:13 | 1 | try.ps1:58:12:58:13 | 1 | |
-| try.ps1:61:1:70:2 | test-try-two-catch-specific-1 | try.ps1:72:1:79:2 | test-try-catch-specific-2 | |
-| try.ps1:61:40:70:2 | enter {...} | try.ps1:61:40:70:2 | {...} | |
-| try.ps1:61:40:70:2 | exit {...} (normal) | try.ps1:61:40:70:2 | exit {...} | |
-| try.ps1:61:40:70:2 | {...} | try.ps1:62:5:69:13 | {...} | |
-| try.ps1:62:5:68:6 | try {...} | try.ps1:62:9:64:6 | {...} | |
-| try.ps1:62:5:69:13 | {...} | try.ps1:62:5:68:6 | try {...} | |
-| try.ps1:62:9:64:6 | {...} | try.ps1:63:9:63:21 | Write-Output | |
-| try.ps1:63:9:63:21 | Write-Output | try.ps1:63:22:63:30 | Hello! | |
-| try.ps1:63:9:63:30 | call to Write-Output | try.ps1:69:5:69:13 | return ... | |
-| try.ps1:63:22:63:30 | Hello! | try.ps1:63:9:63:30 | call to Write-Output | |
-| try.ps1:69:5:69:13 | return ... | try.ps1:69:12:69:13 | 2 | |
-| try.ps1:69:12:69:13 | 2 | try.ps1:61:40:70:2 | exit {...} (normal) | |
-| try.ps1:69:12:69:13 | 2 | try.ps1:69:12:69:13 | 2 | |
-| try.ps1:72:1:79:2 | test-try-catch-specific-2 | try.ps1:81:1:90:2 | test-try-two-catch-specific-2 | |
-| try.ps1:72:36:79:2 | enter {...} | try.ps1:72:36:79:2 | {...} | |
-| try.ps1:72:36:79:2 | exit {...} (normal) | try.ps1:72:36:79:2 | exit {...} | |
-| try.ps1:72:36:79:2 | {...} | try.ps1:73:5:78:13 | {...} | |
-| try.ps1:73:5:77:6 | try {...} | try.ps1:73:9:75:6 | {...} | |
-| try.ps1:73:5:78:13 | {...} | try.ps1:73:5:77:6 | try {...} | |
-| try.ps1:73:9:75:6 | {...} | try.ps1:74:9:74:21 | Write-Output | |
-| try.ps1:74:9:74:21 | Write-Output | try.ps1:74:22:74:30 | Hello! | |
-| try.ps1:74:9:74:30 | call to Write-Output | try.ps1:78:5:78:13 | return ... | |
-| try.ps1:74:22:74:30 | Hello! | try.ps1:74:9:74:30 | call to Write-Output | |
-| try.ps1:78:5:78:13 | return ... | try.ps1:78:12:78:13 | 1 | |
-| try.ps1:78:12:78:13 | 1 | try.ps1:72:36:79:2 | exit {...} (normal) | |
-| try.ps1:78:12:78:13 | 1 | try.ps1:78:12:78:13 | 1 | |
-| try.ps1:81:1:90:2 | test-try-two-catch-specific-2 | try.ps1:92:1:103:2 | test-try-three-catch-specific-2 | |
-| try.ps1:81:40:90:2 | enter {...} | try.ps1:81:40:90:2 | {...} | |
-| try.ps1:81:40:90:2 | exit {...} (normal) | try.ps1:81:40:90:2 | exit {...} | |
-| try.ps1:81:40:90:2 | {...} | try.ps1:82:5:89:13 | {...} | |
-| try.ps1:82:5:88:6 | try {...} | try.ps1:82:9:84:6 | {...} | |
-| try.ps1:82:5:89:13 | {...} | try.ps1:82:5:88:6 | try {...} | |
-| try.ps1:82:9:84:6 | {...} | try.ps1:83:9:83:21 | Write-Output | |
-| try.ps1:83:9:83:21 | Write-Output | try.ps1:83:22:83:30 | Hello! | |
-| try.ps1:83:9:83:30 | call to Write-Output | try.ps1:89:5:89:13 | return ... | |
-| try.ps1:83:22:83:30 | Hello! | try.ps1:83:9:83:30 | call to Write-Output | |
-| try.ps1:89:5:89:13 | return ... | try.ps1:89:12:89:13 | 2 | |
-| try.ps1:89:12:89:13 | 2 | try.ps1:81:40:90:2 | exit {...} (normal) | |
-| try.ps1:89:12:89:13 | 2 | try.ps1:89:12:89:13 | 2 | |
-| try.ps1:92:1:103:2 | test-try-three-catch-specific-2 | try.ps1:105:1:114:2 | test-try-catch-finally | |
-| try.ps1:92:42:103:2 | enter {...} | try.ps1:92:42:103:2 | {...} | |
-| try.ps1:92:42:103:2 | exit {...} (normal) | try.ps1:92:42:103:2 | exit {...} | |
-| try.ps1:92:42:103:2 | {...} | try.ps1:93:5:102:13 | {...} | |
-| try.ps1:93:5:101:6 | try {...} | try.ps1:93:9:95:6 | {...} | |
-| try.ps1:93:5:102:13 | {...} | try.ps1:93:5:101:6 | try {...} | |
-| try.ps1:93:9:95:6 | {...} | try.ps1:94:9:94:21 | Write-Output | |
-| try.ps1:94:9:94:21 | Write-Output | try.ps1:94:22:94:30 | Hello! | |
-| try.ps1:94:9:94:30 | call to Write-Output | try.ps1:102:5:102:13 | return ... | |
-| try.ps1:94:22:94:30 | Hello! | try.ps1:94:9:94:30 | call to Write-Output | |
-| try.ps1:102:5:102:13 | return ... | try.ps1:102:12:102:13 | 3 | |
-| try.ps1:102:12:102:13 | 3 | try.ps1:92:42:103:2 | exit {...} (normal) | |
-| try.ps1:102:12:102:13 | 3 | try.ps1:102:12:102:13 | 3 | |
-| try.ps1:105:1:114:2 | test-try-catch-finally | try.ps1:116:1:123:2 | test-try-finally | |
-| try.ps1:105:33:114:2 | enter {...} | try.ps1:105:33:114:2 | {...} | |
-| try.ps1:105:33:114:2 | exit {...} (normal) | try.ps1:105:33:114:2 | exit {...} | |
-| try.ps1:105:33:114:2 | {...} | try.ps1:106:5:113:13 | {...} | |
-| try.ps1:106:5:112:6 | try {...} | try.ps1:106:9:108:6 | {...} | |
-| try.ps1:106:5:113:13 | {...} | try.ps1:106:5:112:6 | try {...} | |
-| try.ps1:106:9:108:6 | {...} | try.ps1:107:9:107:21 | Write-Output | |
-| try.ps1:107:9:107:21 | Write-Output | try.ps1:107:22:107:30 | Hello! | |
-| try.ps1:107:9:107:30 | call to Write-Output | try.ps1:110:15:112:6 | {...} | |
-| try.ps1:107:22:107:30 | Hello! | try.ps1:107:9:107:30 | call to Write-Output | |
-| try.ps1:110:15:112:6 | {...} | try.ps1:111:9:111:21 | Write-Output | |
-| try.ps1:111:9:111:21 | Write-Output | try.ps1:111:22:111:32 | Finally! | |
-| try.ps1:111:9:111:32 | call to Write-Output | try.ps1:113:5:113:13 | return ... | |
-| try.ps1:111:22:111:32 | Finally! | try.ps1:111:9:111:32 | call to Write-Output | |
-| try.ps1:113:5:113:13 | return ... | try.ps1:113:12:113:13 | 1 | |
-| try.ps1:113:12:113:13 | 1 | try.ps1:105:33:114:2 | exit {...} (normal) | |
-| try.ps1:113:12:113:13 | 1 | try.ps1:113:12:113:13 | 1 | |
-| try.ps1:116:1:123:2 | test-try-finally | try.ps1:125:1:134:2 | test-try-finally-catch-specific-1 | |
-| try.ps1:116:27:123:2 | enter {...} | try.ps1:116:27:123:2 | {...} | |
-| try.ps1:116:27:123:2 | exit {...} (normal) | try.ps1:116:27:123:2 | exit {...} | |
-| try.ps1:116:27:123:2 | {...} | try.ps1:117:5:122:13 | {...} | |
-| try.ps1:117:5:121:6 | try {...} | try.ps1:117:9:119:6 | {...} | |
-| try.ps1:117:5:122:13 | {...} | try.ps1:117:5:121:6 | try {...} | |
-| try.ps1:117:9:119:6 | {...} | try.ps1:118:9:118:21 | Write-Output | |
-| try.ps1:118:9:118:21 | Write-Output | try.ps1:118:22:118:30 | Hello! | |
-| try.ps1:118:9:118:30 | call to Write-Output | try.ps1:119:15:121:6 | {...} | |
-| try.ps1:118:22:118:30 | Hello! | try.ps1:118:9:118:30 | call to Write-Output | |
-| try.ps1:119:15:121:6 | {...} | try.ps1:120:9:120:21 | Write-Output | |
-| try.ps1:120:9:120:21 | Write-Output | try.ps1:120:22:120:32 | Finally! | |
-| try.ps1:120:9:120:32 | call to Write-Output | try.ps1:122:5:122:13 | return ... | |
-| try.ps1:120:22:120:32 | Finally! | try.ps1:120:9:120:32 | call to Write-Output | |
-| try.ps1:122:5:122:13 | return ... | try.ps1:122:12:122:13 | 1 | |
-| try.ps1:122:12:122:13 | 1 | try.ps1:116:27:123:2 | exit {...} (normal) | |
-| try.ps1:122:12:122:13 | 1 | try.ps1:122:12:122:13 | 1 | |
-| try.ps1:125:1:134:2 | test-try-finally-catch-specific-1 | try.ps1:136:1:147:2 | test-nested-try-inner-finally | |
-| try.ps1:125:44:134:2 | enter {...} | try.ps1:125:44:134:2 | {...} | |
-| try.ps1:125:44:134:2 | exit {...} (normal) | try.ps1:125:44:134:2 | exit {...} | |
-| try.ps1:125:44:134:2 | {...} | try.ps1:126:5:133:13 | {...} | |
-| try.ps1:126:5:132:6 | try {...} | try.ps1:126:9:128:6 | {...} | |
-| try.ps1:126:5:133:13 | {...} | try.ps1:126:5:132:6 | try {...} | |
-| try.ps1:126:9:128:6 | {...} | try.ps1:127:9:127:21 | Write-Output | |
-| try.ps1:127:9:127:21 | Write-Output | try.ps1:127:22:127:30 | Hello! | |
-| try.ps1:127:9:127:30 | call to Write-Output | try.ps1:130:15:132:6 | {...} | |
-| try.ps1:127:22:127:30 | Hello! | try.ps1:127:9:127:30 | call to Write-Output | |
-| try.ps1:130:15:132:6 | {...} | try.ps1:131:9:131:21 | Write-Output | |
-| try.ps1:131:9:131:21 | Write-Output | try.ps1:131:22:131:32 | Finally! | |
-| try.ps1:131:9:131:32 | call to Write-Output | try.ps1:133:5:133:13 | return ... | |
-| try.ps1:131:22:131:32 | Finally! | try.ps1:131:9:131:32 | call to Write-Output | |
-| try.ps1:133:5:133:13 | return ... | try.ps1:133:12:133:13 | 1 | |
-| try.ps1:133:12:133:13 | 1 | try.ps1:125:44:134:2 | exit {...} (normal) | |
-| try.ps1:133:12:133:13 | 1 | try.ps1:133:12:133:13 | 1 | |
-| try.ps1:136:1:147:2 | test-nested-try-inner-finally | try.ps1:149:1:162:2 | test-nested-try-inner-finally | |
-| try.ps1:136:40:147:2 | enter {...} | try.ps1:136:40:147:2 | {...} | |
-| try.ps1:136:40:147:2 | exit {...} (normal) | try.ps1:136:40:147:2 | exit {...} | |
-| try.ps1:136:40:147:2 | {...} | try.ps1:137:5:146:13 | {...} | |
-| try.ps1:137:5:145:6 | try {...} | try.ps1:137:9:143:6 | {...} | |
-| try.ps1:137:5:146:13 | {...} | try.ps1:137:5:145:6 | try {...} | |
-| try.ps1:137:9:143:6 | {...} | try.ps1:138:9:142:10 | try {...} | |
-| try.ps1:138:9:142:10 | try {...} | try.ps1:138:13:140:10 | {...} | |
-| try.ps1:138:13:140:10 | {...} | try.ps1:139:13:139:25 | Write-Output | |
-| try.ps1:139:13:139:25 | Write-Output | try.ps1:139:26:139:34 | Hello! | |
-| try.ps1:139:13:139:34 | call to Write-Output | try.ps1:146:5:146:13 | return ... | |
-| try.ps1:139:26:139:34 | Hello! | try.ps1:139:13:139:34 | call to Write-Output | |
-| try.ps1:146:5:146:13 | return ... | try.ps1:146:12:146:13 | 1 | |
-| try.ps1:146:12:146:13 | 1 | try.ps1:136:40:147:2 | exit {...} (normal) | |
-| try.ps1:146:12:146:13 | 1 | try.ps1:146:12:146:13 | 1 | |
-| try.ps1:149:1:162:2 | test-nested-try-inner-finally | try.ps1:164:1:177:2 | test-nested-try-outer-finally | |
-| try.ps1:149:40:162:2 | enter {...} | try.ps1:149:40:162:2 | {...} | |
-| try.ps1:149:40:162:2 | exit {...} (normal) | try.ps1:149:40:162:2 | exit {...} | |
-| try.ps1:149:40:162:2 | {...} | try.ps1:150:5:161:13 | {...} | |
-| try.ps1:150:5:160:6 | try {...} | try.ps1:150:9:158:6 | {...} | |
-| try.ps1:150:5:161:13 | {...} | try.ps1:150:5:160:6 | try {...} | |
-| try.ps1:150:9:158:6 | {...} | try.ps1:151:9:157:10 | try {...} | |
-| try.ps1:151:9:157:10 | try {...} | try.ps1:151:13:153:10 | {...} | |
-| try.ps1:151:13:153:10 | {...} | try.ps1:152:13:152:25 | Write-Output | |
-| try.ps1:152:13:152:25 | Write-Output | try.ps1:152:26:152:34 | Hello! | |
-| try.ps1:152:13:152:34 | call to Write-Output | try.ps1:155:19:157:10 | {...} | |
-| try.ps1:152:26:152:34 | Hello! | try.ps1:152:13:152:34 | call to Write-Output | |
-| try.ps1:155:19:157:10 | {...} | try.ps1:156:13:156:25 | Write-Output | |
-| try.ps1:156:13:156:25 | Write-Output | try.ps1:156:26:156:36 | Finally! | |
-| try.ps1:156:13:156:36 | call to Write-Output | try.ps1:161:5:161:13 | return ... | |
-| try.ps1:156:26:156:36 | Finally! | try.ps1:156:13:156:36 | call to Write-Output | |
-| try.ps1:161:5:161:13 | return ... | try.ps1:161:12:161:13 | 1 | |
-| try.ps1:161:12:161:13 | 1 | try.ps1:149:40:162:2 | exit {...} (normal) | |
-| try.ps1:161:12:161:13 | 1 | try.ps1:161:12:161:13 | 1 | |
-| try.ps1:164:1:177:2 | test-nested-try-outer-finally | try.ps1:179:1:194:2 | test-nested-try-inner-outer-finally | |
-| try.ps1:164:40:177:2 | enter {...} | try.ps1:164:40:177:2 | {...} | |
-| try.ps1:164:40:177:2 | exit {...} (normal) | try.ps1:164:40:177:2 | exit {...} | |
-| try.ps1:164:40:177:2 | {...} | try.ps1:165:5:176:13 | {...} | |
-| try.ps1:165:5:175:6 | try {...} | try.ps1:165:9:171:6 | {...} | |
-| try.ps1:165:5:176:13 | {...} | try.ps1:165:5:175:6 | try {...} | |
-| try.ps1:165:9:171:6 | {...} | try.ps1:166:9:170:10 | try {...} | |
-| try.ps1:166:9:170:10 | try {...} | try.ps1:166:13:168:10 | {...} | |
-| try.ps1:166:13:168:10 | {...} | try.ps1:167:13:167:25 | Write-Output | |
-| try.ps1:167:13:167:25 | Write-Output | try.ps1:167:26:167:34 | Hello! | |
-| try.ps1:167:13:167:34 | call to Write-Output | try.ps1:173:15:175:6 | {...} | |
-| try.ps1:167:26:167:34 | Hello! | try.ps1:167:13:167:34 | call to Write-Output | |
-| try.ps1:173:15:175:6 | {...} | try.ps1:174:9:174:21 | Write-Output | |
-| try.ps1:174:9:174:21 | Write-Output | try.ps1:174:22:174:32 | Finally! | |
-| try.ps1:174:9:174:32 | call to Write-Output | try.ps1:176:5:176:13 | return ... | |
-| try.ps1:174:22:174:32 | Finally! | try.ps1:174:9:174:32 | call to Write-Output | |
-| try.ps1:176:5:176:13 | return ... | try.ps1:176:12:176:13 | 1 | |
-| try.ps1:176:12:176:13 | 1 | try.ps1:164:40:177:2 | exit {...} (normal) | |
-| try.ps1:176:12:176:13 | 1 | try.ps1:176:12:176:13 | 1 | |
-| try.ps1:179:1:194:2 | test-nested-try-inner-outer-finally | try.ps1:1:1:194:2 | exit try.ps1 (normal) | |
-| try.ps1:179:46:194:2 | enter {...} | try.ps1:179:46:194:2 | {...} | |
-| try.ps1:179:46:194:2 | exit {...} (normal) | try.ps1:179:46:194:2 | exit {...} | |
-| try.ps1:179:46:194:2 | {...} | try.ps1:180:5:193:13 | {...} | |
-| try.ps1:180:5:192:6 | try {...} | try.ps1:180:9:188:6 | {...} | |
-| try.ps1:180:5:193:13 | {...} | try.ps1:180:5:192:6 | try {...} | |
-| try.ps1:180:9:188:6 | {...} | try.ps1:181:9:187:10 | try {...} | |
-| try.ps1:181:9:187:10 | try {...} | try.ps1:181:13:183:10 | {...} | |
-| try.ps1:181:13:183:10 | {...} | try.ps1:182:13:182:25 | Write-Output | |
-| try.ps1:182:13:182:25 | Write-Output | try.ps1:182:26:182:34 | Hello! | |
-| try.ps1:182:13:182:34 | call to Write-Output | try.ps1:185:19:187:10 | {...} | |
-| try.ps1:182:26:182:34 | Hello! | try.ps1:182:13:182:34 | call to Write-Output | |
-| try.ps1:185:19:187:10 | {...} | try.ps1:186:13:186:25 | Write-Output | |
-| try.ps1:186:13:186:25 | Write-Output | try.ps1:186:26:186:36 | Finally! | |
-| try.ps1:186:13:186:36 | call to Write-Output | try.ps1:190:15:192:6 | {...} | |
-| try.ps1:186:26:186:36 | Finally! | try.ps1:186:13:186:36 | call to Write-Output | |
-| try.ps1:190:15:192:6 | {...} | try.ps1:191:9:191:21 | Write-Output | |
-| try.ps1:191:9:191:21 | Write-Output | try.ps1:191:22:191:32 | Finally! | |
-| try.ps1:191:9:191:32 | call to Write-Output | try.ps1:193:5:193:13 | return ... | |
-| try.ps1:191:22:191:32 | Finally! | try.ps1:191:9:191:32 | call to Write-Output | |
-| try.ps1:193:5:193:13 | return ... | try.ps1:193:12:193:13 | 1 | |
-| try.ps1:193:12:193:13 | 1 | try.ps1:179:46:194:2 | exit {...} (normal) | |
-| try.ps1:193:12:193:13 | 1 | try.ps1:193:12:193:13 | 1 | |
+| conditionals.ps1:1:1:9:1 | def of test-if | conditionals.ps1:11:1:22:1 | def of test-if-else | |
+| conditionals.ps1:1:1:129:1 | enter {...} | conditionals.ps1:1:1:129:1 | {...} | |
+| conditionals.ps1:1:1:129:1 | exit {...} (normal) | conditionals.ps1:1:1:129:1 | exit {...} | |
+| conditionals.ps1:1:1:129:1 | {...} | conditionals.ps1:1:1:9:1 | def of test-if | |
+| conditionals.ps1:1:1:129:1 | {...} | conditionals.ps1:1:1:129:1 | {...} | |
+| conditionals.ps1:1:18:9:1 | [synth] pipeline | conditionals.ps1:2:5:8:13 | {...} | |
+| conditionals.ps1:1:18:9:1 | enter {...} | conditionals.ps1:1:18:9:1 | {...} | |
+| conditionals.ps1:1:18:9:1 | exit {...} (normal) | conditionals.ps1:1:18:9:1 | exit {...} | |
+| conditionals.ps1:1:18:9:1 | myBool | conditionals.ps1:1:18:9:1 | [synth] pipeline | |
+| conditionals.ps1:1:18:9:1 | {...} | conditionals.ps1:1:18:9:1 | myBool | |
+| conditionals.ps1:2:5:8:13 | {...} | conditionals.ps1:4:5:7:5 | [Stmt] if (...) {...} | |
+| conditionals.ps1:4:5:7:5 | [Stmt] if (...) {...} | conditionals.ps1:4:8:4:14 | myBool | |
+| conditionals.ps1:4:5:7:5 | if (...) {...} | conditionals.ps1:8:5:8:13 | return ... | |
+| conditionals.ps1:4:8:4:14 | myBool | conditionals.ps1:4:5:7:5 | if (...) {...} | false |
+| conditionals.ps1:4:8:4:14 | myBool | conditionals.ps1:5:5:7:5 | {...} | true |
+| conditionals.ps1:5:5:7:5 | {...} | conditionals.ps1:6:9:6:17 | return ... | |
+| conditionals.ps1:6:9:6:17 | return ... | conditionals.ps1:6:16:6:17 | 10 | |
+| conditionals.ps1:6:16:6:17 | 10 | conditionals.ps1:4:5:7:5 | if (...) {...} | |
+| conditionals.ps1:8:5:8:13 | return ... | conditionals.ps1:8:12:8:13 | 11 | |
+| conditionals.ps1:8:12:8:13 | 11 | conditionals.ps1:1:18:9:1 | exit {...} (normal) | |
+| conditionals.ps1:11:1:22:1 | def of test-if-else | conditionals.ps1:24:1:32:1 | def of test-if-conj | |
+| conditionals.ps1:11:23:22:1 | [synth] pipeline | conditionals.ps1:12:5:21:5 | {...} | |
+| conditionals.ps1:11:23:22:1 | enter {...} | conditionals.ps1:11:23:22:1 | {...} | |
+| conditionals.ps1:11:23:22:1 | exit {...} (normal) | conditionals.ps1:11:23:22:1 | exit {...} | |
+| conditionals.ps1:11:23:22:1 | myBool | conditionals.ps1:11:23:22:1 | [synth] pipeline | |
+| conditionals.ps1:11:23:22:1 | {...} | conditionals.ps1:11:23:22:1 | myBool | |
+| conditionals.ps1:12:5:21:5 | {...} | conditionals.ps1:14:5:21:5 | [Stmt] if (...) {...} else {...} | |
+| conditionals.ps1:14:5:21:5 | [Stmt] if (...) {...} else {...} | conditionals.ps1:14:8:14:14 | myBool | |
+| conditionals.ps1:14:5:21:5 | if (...) {...} else {...} | conditionals.ps1:11:23:22:1 | exit {...} (normal) | |
+| conditionals.ps1:14:8:14:14 | myBool | conditionals.ps1:15:5:17:5 | {...} | true |
+| conditionals.ps1:14:8:14:14 | myBool | conditionals.ps1:19:5:21:5 | {...} | false |
+| conditionals.ps1:15:5:17:5 | {...} | conditionals.ps1:16:9:16:17 | return ... | |
+| conditionals.ps1:16:9:16:17 | return ... | conditionals.ps1:16:16:16:17 | 10 | |
+| conditionals.ps1:16:16:16:17 | 10 | conditionals.ps1:14:5:21:5 | if (...) {...} else {...} | |
+| conditionals.ps1:19:5:21:5 | {...} | conditionals.ps1:20:9:20:17 | return ... | |
+| conditionals.ps1:20:9:20:17 | return ... | conditionals.ps1:20:16:20:17 | 11 | |
+| conditionals.ps1:20:16:20:17 | 11 | conditionals.ps1:14:5:21:5 | if (...) {...} else {...} | |
+| conditionals.ps1:24:1:32:1 | def of test-if-conj | conditionals.ps1:34:1:45:1 | def of test-if-else-conj | |
+| conditionals.ps1:24:23:32:1 | [synth] pipeline | conditionals.ps1:25:5:31:13 | {...} | |
+| conditionals.ps1:24:23:32:1 | enter {...} | conditionals.ps1:24:23:32:1 | {...} | |
+| conditionals.ps1:24:23:32:1 | exit {...} (normal) | conditionals.ps1:24:23:32:1 | exit {...} | |
+| conditionals.ps1:24:23:32:1 | myBool1 | conditionals.ps1:24:23:32:1 | myBool2 | |
+| conditionals.ps1:24:23:32:1 | myBool2 | conditionals.ps1:24:23:32:1 | [synth] pipeline | |
+| conditionals.ps1:24:23:32:1 | {...} | conditionals.ps1:24:23:32:1 | myBool1 | |
+| conditionals.ps1:25:5:31:13 | {...} | conditionals.ps1:27:5:30:5 | [Stmt] if (...) {...} | |
+| conditionals.ps1:27:5:30:5 | [Stmt] if (...) {...} | conditionals.ps1:27:8:27:15 | myBool1 | |
+| conditionals.ps1:27:5:30:5 | if (...) {...} | conditionals.ps1:31:5:31:13 | return ... | |
+| conditionals.ps1:27:8:27:15 | myBool1 | conditionals.ps1:27:22:27:29 | myBool2 | false, true |
+| conditionals.ps1:27:8:27:29 | [false] ... -and ... | conditionals.ps1:27:5:30:5 | if (...) {...} | false |
+| conditionals.ps1:27:8:27:29 | [true] ... -and ... | conditionals.ps1:28:5:30:5 | {...} | true |
+| conditionals.ps1:27:22:27:29 | myBool2 | conditionals.ps1:27:8:27:29 | [false] ... -and ... | false |
+| conditionals.ps1:27:22:27:29 | myBool2 | conditionals.ps1:27:8:27:29 | [true] ... -and ... | true |
+| conditionals.ps1:28:5:30:5 | {...} | conditionals.ps1:29:9:29:17 | return ... | |
+| conditionals.ps1:29:9:29:17 | return ... | conditionals.ps1:29:16:29:17 | 10 | |
+| conditionals.ps1:29:16:29:17 | 10 | conditionals.ps1:27:5:30:5 | if (...) {...} | |
+| conditionals.ps1:31:5:31:13 | return ... | conditionals.ps1:31:12:31:13 | 11 | |
+| conditionals.ps1:31:12:31:13 | 11 | conditionals.ps1:24:23:32:1 | exit {...} (normal) | |
+| conditionals.ps1:34:1:45:1 | def of test-if-else-conj | conditionals.ps1:47:1:55:1 | def of test-if-disj | |
+| conditionals.ps1:34:28:45:1 | [synth] pipeline | conditionals.ps1:35:5:44:5 | {...} | |
+| conditionals.ps1:34:28:45:1 | enter {...} | conditionals.ps1:34:28:45:1 | {...} | |
+| conditionals.ps1:34:28:45:1 | exit {...} (normal) | conditionals.ps1:34:28:45:1 | exit {...} | |
+| conditionals.ps1:34:28:45:1 | myBool1 | conditionals.ps1:34:28:45:1 | myBool2 | |
+| conditionals.ps1:34:28:45:1 | myBool2 | conditionals.ps1:34:28:45:1 | [synth] pipeline | |
+| conditionals.ps1:34:28:45:1 | {...} | conditionals.ps1:34:28:45:1 | myBool1 | |
+| conditionals.ps1:35:5:44:5 | {...} | conditionals.ps1:37:5:44:5 | [Stmt] if (...) {...} else {...} | |
+| conditionals.ps1:37:5:44:5 | [Stmt] if (...) {...} else {...} | conditionals.ps1:37:8:37:15 | myBool1 | |
+| conditionals.ps1:37:5:44:5 | if (...) {...} else {...} | conditionals.ps1:34:28:45:1 | exit {...} (normal) | |
+| conditionals.ps1:37:8:37:15 | myBool1 | conditionals.ps1:37:22:37:29 | myBool2 | false, true |
+| conditionals.ps1:37:8:37:29 | [false] ... -and ... | conditionals.ps1:42:5:44:5 | {...} | false |
+| conditionals.ps1:37:8:37:29 | [true] ... -and ... | conditionals.ps1:38:5:40:5 | {...} | true |
+| conditionals.ps1:37:22:37:29 | myBool2 | conditionals.ps1:37:8:37:29 | [false] ... -and ... | false |
+| conditionals.ps1:37:22:37:29 | myBool2 | conditionals.ps1:37:8:37:29 | [true] ... -and ... | true |
+| conditionals.ps1:38:5:40:5 | {...} | conditionals.ps1:39:9:39:17 | return ... | |
+| conditionals.ps1:39:9:39:17 | return ... | conditionals.ps1:39:16:39:17 | 10 | |
+| conditionals.ps1:39:16:39:17 | 10 | conditionals.ps1:37:5:44:5 | if (...) {...} else {...} | |
+| conditionals.ps1:42:5:44:5 | {...} | conditionals.ps1:43:9:43:17 | return ... | |
+| conditionals.ps1:43:9:43:17 | return ... | conditionals.ps1:43:16:43:17 | 11 | |
+| conditionals.ps1:43:16:43:17 | 11 | conditionals.ps1:37:5:44:5 | if (...) {...} else {...} | |
+| conditionals.ps1:47:1:55:1 | def of test-if-disj | conditionals.ps1:57:1:68:1 | def of test-if-else-disj | |
+| conditionals.ps1:47:23:55:1 | [synth] pipeline | conditionals.ps1:48:5:54:13 | {...} | |
+| conditionals.ps1:47:23:55:1 | enter {...} | conditionals.ps1:47:23:55:1 | {...} | |
+| conditionals.ps1:47:23:55:1 | exit {...} (normal) | conditionals.ps1:47:23:55:1 | exit {...} | |
+| conditionals.ps1:47:23:55:1 | myBool1 | conditionals.ps1:47:23:55:1 | myBool2 | |
+| conditionals.ps1:47:23:55:1 | myBool2 | conditionals.ps1:47:23:55:1 | [synth] pipeline | |
+| conditionals.ps1:47:23:55:1 | {...} | conditionals.ps1:47:23:55:1 | myBool1 | |
+| conditionals.ps1:48:5:54:13 | {...} | conditionals.ps1:50:5:53:5 | [Stmt] if (...) {...} | |
+| conditionals.ps1:50:5:53:5 | [Stmt] if (...) {...} | conditionals.ps1:50:8:50:15 | myBool1 | |
+| conditionals.ps1:50:5:53:5 | if (...) {...} | conditionals.ps1:54:5:54:13 | return ... | |
+| conditionals.ps1:50:8:50:15 | myBool1 | conditionals.ps1:50:21:50:28 | myBool2 | false, true |
+| conditionals.ps1:50:8:50:28 | [false] ... -or ... | conditionals.ps1:50:5:53:5 | if (...) {...} | false |
+| conditionals.ps1:50:8:50:28 | [true] ... -or ... | conditionals.ps1:51:5:53:5 | {...} | true |
+| conditionals.ps1:50:21:50:28 | myBool2 | conditionals.ps1:50:8:50:28 | [false] ... -or ... | false |
+| conditionals.ps1:50:21:50:28 | myBool2 | conditionals.ps1:50:8:50:28 | [true] ... -or ... | true |
+| conditionals.ps1:51:5:53:5 | {...} | conditionals.ps1:52:9:52:17 | return ... | |
+| conditionals.ps1:52:9:52:17 | return ... | conditionals.ps1:52:16:52:17 | 10 | |
+| conditionals.ps1:52:16:52:17 | 10 | conditionals.ps1:50:5:53:5 | if (...) {...} | |
+| conditionals.ps1:54:5:54:13 | return ... | conditionals.ps1:54:12:54:13 | 11 | |
+| conditionals.ps1:54:12:54:13 | 11 | conditionals.ps1:47:23:55:1 | exit {...} (normal) | |
+| conditionals.ps1:57:1:68:1 | def of test-if-else-disj | conditionals.ps1:70:1:82:1 | def of test-else-if | |
+| conditionals.ps1:57:28:68:1 | [synth] pipeline | conditionals.ps1:58:5:67:5 | {...} | |
+| conditionals.ps1:57:28:68:1 | enter {...} | conditionals.ps1:57:28:68:1 | {...} | |
+| conditionals.ps1:57:28:68:1 | exit {...} (normal) | conditionals.ps1:57:28:68:1 | exit {...} | |
+| conditionals.ps1:57:28:68:1 | myBool1 | conditionals.ps1:57:28:68:1 | myBool2 | |
+| conditionals.ps1:57:28:68:1 | myBool2 | conditionals.ps1:57:28:68:1 | [synth] pipeline | |
+| conditionals.ps1:57:28:68:1 | {...} | conditionals.ps1:57:28:68:1 | myBool1 | |
+| conditionals.ps1:58:5:67:5 | {...} | conditionals.ps1:60:5:67:5 | [Stmt] if (...) {...} else {...} | |
+| conditionals.ps1:60:5:67:5 | [Stmt] if (...) {...} else {...} | conditionals.ps1:60:8:60:15 | myBool1 | |
+| conditionals.ps1:60:5:67:5 | if (...) {...} else {...} | conditionals.ps1:57:28:68:1 | exit {...} (normal) | |
+| conditionals.ps1:60:8:60:15 | myBool1 | conditionals.ps1:60:21:60:28 | myBool2 | false, true |
+| conditionals.ps1:60:8:60:28 | [false] ... -or ... | conditionals.ps1:65:5:67:5 | {...} | false |
+| conditionals.ps1:60:8:60:28 | [true] ... -or ... | conditionals.ps1:61:5:63:5 | {...} | true |
+| conditionals.ps1:60:21:60:28 | myBool2 | conditionals.ps1:60:8:60:28 | [false] ... -or ... | false |
+| conditionals.ps1:60:21:60:28 | myBool2 | conditionals.ps1:60:8:60:28 | [true] ... -or ... | true |
+| conditionals.ps1:61:5:63:5 | {...} | conditionals.ps1:62:9:62:17 | return ... | |
+| conditionals.ps1:62:9:62:17 | return ... | conditionals.ps1:62:16:62:17 | 10 | |
+| conditionals.ps1:62:16:62:17 | 10 | conditionals.ps1:60:5:67:5 | if (...) {...} else {...} | |
+| conditionals.ps1:65:5:67:5 | {...} | conditionals.ps1:66:9:66:17 | return ... | |
+| conditionals.ps1:66:9:66:17 | return ... | conditionals.ps1:66:16:66:17 | 11 | |
+| conditionals.ps1:66:16:66:17 | 11 | conditionals.ps1:60:5:67:5 | if (...) {...} else {...} | |
+| conditionals.ps1:70:1:82:1 | def of test-else-if | conditionals.ps1:84:1:99:1 | def of test-else-if-else | |
+| conditionals.ps1:70:23:82:1 | [synth] pipeline | conditionals.ps1:71:5:81:13 | {...} | |
+| conditionals.ps1:70:23:82:1 | enter {...} | conditionals.ps1:70:23:82:1 | {...} | |
+| conditionals.ps1:70:23:82:1 | exit {...} (normal) | conditionals.ps1:70:23:82:1 | exit {...} | |
+| conditionals.ps1:70:23:82:1 | myBool1 | conditionals.ps1:70:23:82:1 | myBool2 | |
+| conditionals.ps1:70:23:82:1 | myBool2 | conditionals.ps1:70:23:82:1 | [synth] pipeline | |
+| conditionals.ps1:70:23:82:1 | {...} | conditionals.ps1:70:23:82:1 | myBool1 | |
+| conditionals.ps1:71:5:81:13 | {...} | conditionals.ps1:73:5:80:5 | [Stmt] if (...) {...} | |
+| conditionals.ps1:73:5:80:5 | [Stmt] if (...) {...} | conditionals.ps1:73:8:73:15 | myBool1 | |
+| conditionals.ps1:73:5:80:5 | if (...) {...} | conditionals.ps1:81:5:81:13 | return ... | |
+| conditionals.ps1:73:8:73:15 | myBool1 | conditionals.ps1:73:5:80:5 | if (...) {...} | false |
+| conditionals.ps1:73:8:73:15 | myBool1 | conditionals.ps1:74:5:76:5 | {...} | true |
+| conditionals.ps1:74:5:76:5 | {...} | conditionals.ps1:75:9:75:17 | return ... | |
+| conditionals.ps1:75:9:75:17 | return ... | conditionals.ps1:75:16:75:17 | 10 | |
+| conditionals.ps1:75:16:75:17 | 10 | conditionals.ps1:73:5:80:5 | if (...) {...} | |
+| conditionals.ps1:81:5:81:13 | return ... | conditionals.ps1:81:12:81:13 | 12 | |
+| conditionals.ps1:81:12:81:13 | 12 | conditionals.ps1:70:23:82:1 | exit {...} (normal) | |
+| conditionals.ps1:84:1:99:1 | def of test-else-if-else | conditionals.ps1:101:1:108:1 | def of test-switch | |
+| conditionals.ps1:84:28:99:1 | [synth] pipeline | conditionals.ps1:85:5:98:5 | {...} | |
+| conditionals.ps1:84:28:99:1 | enter {...} | conditionals.ps1:84:28:99:1 | {...} | |
+| conditionals.ps1:84:28:99:1 | exit {...} (normal) | conditionals.ps1:84:28:99:1 | exit {...} | |
+| conditionals.ps1:84:28:99:1 | myBool1 | conditionals.ps1:84:28:99:1 | myBool2 | |
+| conditionals.ps1:84:28:99:1 | myBool2 | conditionals.ps1:84:28:99:1 | [synth] pipeline | |
+| conditionals.ps1:84:28:99:1 | {...} | conditionals.ps1:84:28:99:1 | myBool1 | |
+| conditionals.ps1:85:5:98:5 | {...} | conditionals.ps1:87:5:98:5 | [Stmt] if (...) {...} else {...} | |
+| conditionals.ps1:87:5:98:5 | [Stmt] if (...) {...} else {...} | conditionals.ps1:87:8:87:15 | myBool1 | |
+| conditionals.ps1:87:5:98:5 | if (...) {...} else {...} | conditionals.ps1:84:28:99:1 | exit {...} (normal) | |
+| conditionals.ps1:87:8:87:15 | myBool1 | conditionals.ps1:88:5:90:5 | {...} | true |
+| conditionals.ps1:87:8:87:15 | myBool1 | conditionals.ps1:96:5:98:5 | {...} | false |
+| conditionals.ps1:88:5:90:5 | {...} | conditionals.ps1:89:9:89:17 | return ... | |
+| conditionals.ps1:89:9:89:17 | return ... | conditionals.ps1:89:16:89:17 | 10 | |
+| conditionals.ps1:89:16:89:17 | 10 | conditionals.ps1:87:5:98:5 | if (...) {...} else {...} | |
+| conditionals.ps1:96:5:98:5 | {...} | conditionals.ps1:97:9:97:17 | return ... | |
+| conditionals.ps1:97:9:97:17 | return ... | conditionals.ps1:97:16:97:17 | 12 | |
+| conditionals.ps1:97:16:97:17 | 12 | conditionals.ps1:87:5:98:5 | if (...) {...} else {...} | |
+| conditionals.ps1:101:1:108:1 | def of test-switch | conditionals.ps1:110:1:121:1 | def of test-switch-default | |
+| conditionals.ps1:101:26:108:1 | enter {...} | conditionals.ps1:101:26:108:1 | {...} | |
+| conditionals.ps1:101:26:108:1 | exit {...} (normal) | conditionals.ps1:101:26:108:1 | exit {...} | |
+| conditionals.ps1:101:26:108:1 | n | conditionals.ps1:102:5:107:5 | {...} | |
+| conditionals.ps1:101:26:108:1 | {...} | conditionals.ps1:101:26:108:1 | n | |
+| conditionals.ps1:102:5:107:5 | switch(...) {...} | conditionals.ps1:102:12:102:13 | n | |
+| conditionals.ps1:102:5:107:5 | {...} | conditionals.ps1:102:5:107:5 | switch(...) {...} | |
+| conditionals.ps1:102:12:102:13 | n | conditionals.ps1:104:9:104:10 | 0: | |
+| conditionals.ps1:104:9:104:10 | 0: | conditionals.ps1:104:12:104:24 | {...} | true |
+| conditionals.ps1:104:9:104:10 | 0: | conditionals.ps1:105:9:105:10 | 1: | false |
+| conditionals.ps1:104:12:104:24 | {...} | conditionals.ps1:104:14:104:21 | return ... | |
+| conditionals.ps1:104:14:104:21 | return ... | conditionals.ps1:104:21:104:21 | 0 | |
+| conditionals.ps1:104:21:104:21 | 0 | conditionals.ps1:101:26:108:1 | exit {...} (normal) | |
+| conditionals.ps1:105:9:105:10 | 1: | conditionals.ps1:105:12:105:24 | {...} | true |
+| conditionals.ps1:105:9:105:10 | 1: | conditionals.ps1:106:9:106:10 | 2: | false |
+| conditionals.ps1:105:12:105:24 | {...} | conditionals.ps1:105:14:105:21 | return ... | |
+| conditionals.ps1:105:14:105:21 | return ... | conditionals.ps1:105:21:105:21 | 1 | |
+| conditionals.ps1:105:21:105:21 | 1 | conditionals.ps1:101:26:108:1 | exit {...} (normal) | |
+| conditionals.ps1:106:9:106:10 | 2: | conditionals.ps1:101:26:108:1 | exit {...} (normal) | false |
+| conditionals.ps1:106:9:106:10 | 2: | conditionals.ps1:106:12:106:24 | {...} | true |
+| conditionals.ps1:106:12:106:24 | {...} | conditionals.ps1:106:14:106:21 | return ... | |
+| conditionals.ps1:106:14:106:21 | return ... | conditionals.ps1:106:21:106:21 | 2 | |
+| conditionals.ps1:106:21:106:21 | 2 | conditionals.ps1:101:26:108:1 | exit {...} (normal) | |
+| conditionals.ps1:110:1:121:1 | def of test-switch-default | conditionals.ps1:123:1:129:1 | def of test-switch-assign | |
+| conditionals.ps1:110:34:121:1 | enter {...} | conditionals.ps1:110:34:121:1 | {...} | |
+| conditionals.ps1:110:34:121:1 | exit {...} (normal) | conditionals.ps1:110:34:121:1 | exit {...} | |
+| conditionals.ps1:110:34:121:1 | n | conditionals.ps1:111:5:120:5 | {...} | |
+| conditionals.ps1:110:34:121:1 | {...} | conditionals.ps1:110:34:121:1 | n | |
+| conditionals.ps1:111:5:120:5 | switch(...) {...} | conditionals.ps1:111:12:111:13 | n | |
+| conditionals.ps1:111:5:120:5 | {...} | conditionals.ps1:111:5:120:5 | switch(...) {...} | |
+| conditionals.ps1:111:12:111:13 | n | conditionals.ps1:113:9:113:10 | 0: | |
+| conditionals.ps1:113:9:113:10 | 0: | conditionals.ps1:113:12:113:24 | {...} | true |
+| conditionals.ps1:113:9:113:10 | 0: | conditionals.ps1:114:9:114:10 | 1: | false |
+| conditionals.ps1:113:12:113:24 | {...} | conditionals.ps1:113:14:113:21 | return ... | |
+| conditionals.ps1:113:14:113:21 | return ... | conditionals.ps1:113:21:113:21 | 0 | |
+| conditionals.ps1:113:21:113:21 | 0 | conditionals.ps1:110:34:121:1 | exit {...} (normal) | |
+| conditionals.ps1:114:9:114:10 | 1: | conditionals.ps1:114:12:114:24 | {...} | true |
+| conditionals.ps1:114:9:114:10 | 1: | conditionals.ps1:115:9:115:10 | 2: | false |
+| conditionals.ps1:114:12:114:24 | {...} | conditionals.ps1:114:14:114:21 | return ... | |
+| conditionals.ps1:114:14:114:21 | return ... | conditionals.ps1:114:21:114:21 | 1 | |
+| conditionals.ps1:114:21:114:21 | 1 | conditionals.ps1:110:34:121:1 | exit {...} (normal) | |
+| conditionals.ps1:115:9:115:10 | 2: | conditionals.ps1:115:12:115:24 | {...} | true |
+| conditionals.ps1:115:9:115:10 | 2: | conditionals.ps1:116:9:116:16 | default: | false |
+| conditionals.ps1:115:12:115:24 | {...} | conditionals.ps1:115:14:115:21 | return ... | |
+| conditionals.ps1:115:14:115:21 | return ... | conditionals.ps1:115:21:115:21 | 2 | |
+| conditionals.ps1:115:21:115:21 | 2 | conditionals.ps1:110:34:121:1 | exit {...} (normal) | |
+| conditionals.ps1:116:9:116:16 | default: | conditionals.ps1:110:34:121:1 | exit {...} (normal) | false |
+| conditionals.ps1:116:9:116:16 | default: | conditionals.ps1:116:18:119:9 | {...} | true |
+| conditionals.ps1:116:18:119:9 | {...} | conditionals.ps1:117:13:117:33 | [Stmt] Call to Write-Output | |
+| conditionals.ps1:117:13:117:24 | Write-Output | conditionals.ps1:117:26:117:33 | Error! | |
+| conditionals.ps1:117:13:117:33 | Call to Write-Output | conditionals.ps1:118:13:118:20 | return ... | |
+| conditionals.ps1:117:13:117:33 | [Stmt] Call to Write-Output | conditionals.ps1:117:13:117:24 | Write-Output | |
+| conditionals.ps1:117:26:117:33 | Error! | conditionals.ps1:117:13:117:33 | Call to Write-Output | |
+| conditionals.ps1:118:13:118:20 | return ... | conditionals.ps1:118:20:118:20 | 3 | |
+| conditionals.ps1:118:20:118:20 | 3 | conditionals.ps1:110:34:121:1 | exit {...} (normal) | |
+| conditionals.ps1:123:1:129:1 | def of test-switch-assign | conditionals.ps1:1:1:129:1 | exit {...} (normal) | |
+| conditionals.ps1:123:33:129:1 | enter {...} | conditionals.ps1:123:33:129:1 | {...} | |
+| conditionals.ps1:123:33:129:1 | exit {...} (normal) | conditionals.ps1:123:33:129:1 | exit {...} | |
+| conditionals.ps1:123:33:129:1 | n | conditionals.ps1:124:5:128:5 | {...} | |
+| conditionals.ps1:123:33:129:1 | {...} | conditionals.ps1:123:33:129:1 | n | |
+| conditionals.ps1:124:5:124:6 | a | conditionals.ps1:123:33:129:1 | exit {...} (normal) | |
+| conditionals.ps1:124:5:128:5 | ...=... | conditionals.ps1:124:5:124:6 | a | |
+| conditionals.ps1:124:5:128:5 | {...} | conditionals.ps1:124:5:128:5 | ...=... | |
+| functions.ps1:1:1:9:1 | def of Add-Numbers-Arguments | functions.ps1:11:1:11:28 | def of foo | |
+| functions.ps1:1:1:52:1 | {...} | functions.ps1:1:1:9:1 | def of Add-Numbers-Arguments | |
+| functions.ps1:1:1:54:0 | enter {...} | functions.ps1:1:1:54:0 | {...} | |
+| functions.ps1:1:1:54:0 | exit {...} (normal) | functions.ps1:1:1:54:0 | exit {...} | |
+| functions.ps1:1:1:54:0 | {...} | functions.ps1:1:1:52:1 | {...} | |
+| functions.ps1:1:32:9:1 | [synth] pipeline | functions.ps1:3:5:8:23 | {...} | |
+| functions.ps1:1:32:9:1 | enter {...} | functions.ps1:1:32:9:1 | {...} | |
+| functions.ps1:1:32:9:1 | exit {...} (normal) | functions.ps1:1:32:9:1 | exit {...} | |
+| functions.ps1:1:32:9:1 | number1 | functions.ps1:1:32:9:1 | number2 | |
+| functions.ps1:1:32:9:1 | number2 | functions.ps1:1:32:9:1 | [synth] pipeline | |
+| functions.ps1:1:32:9:1 | {...} | functions.ps1:1:32:9:1 | number1 | |
+| functions.ps1:3:5:8:23 | {...} | functions.ps1:8:5:8:23 | [Stmt] ...+... | |
+| functions.ps1:3:5:8:23 | {...} | functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | |
+| functions.ps1:8:5:8:12 | number1 | functions.ps1:8:16:8:23 | number2 | |
+| functions.ps1:8:5:8:23 | ...+... | functions.ps1:1:32:9:1 | exit {...} (normal) | |
+| functions.ps1:8:5:8:23 | [Stmt] ...+... | functions.ps1:8:5:8:12 | number1 | |
+| functions.ps1:8:5:8:23 | [Stmt] ...+... | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | functions.ps1:8:5:8:12 | number1 | |
+| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:8:16:8:23 | number2 | functions.ps1:8:5:8:23 | ...+... | |
+| functions.ps1:11:1:11:28 | def of foo | functions.ps1:13:1:20:1 | def of Default-Arguments | |
+| functions.ps1:11:16:11:28 | [synth] pipeline | functions.ps1:11:18:11:26 | {...} | |
+| functions.ps1:11:16:11:28 | a | functions.ps1:11:16:11:28 | [synth] pipeline | |
+| functions.ps1:11:16:11:28 | enter {...} | functions.ps1:11:16:11:28 | {...} | |
+| functions.ps1:11:16:11:28 | exit {...} (normal) | functions.ps1:11:16:11:28 | exit {...} | |
+| functions.ps1:11:16:11:28 | {...} | functions.ps1:11:16:11:28 | a | |
+| functions.ps1:11:18:11:26 | {...} | functions.ps1:11:16:11:28 | exit {...} (normal) | |
+| functions.ps1:13:1:20:1 | def of Default-Arguments | functions.ps1:22:1:34:1 | def of Add-Numbers-From-Array | |
+| functions.ps1:13:28:20:1 | [synth] pipeline | functions.ps1:14:5:19:18 | {...} | |
+| functions.ps1:13:28:20:1 | enter {...} | functions.ps1:13:28:20:1 | {...} | |
+| functions.ps1:13:28:20:1 | exit {...} (normal) | functions.ps1:13:28:20:1 | exit {...} | |
+| functions.ps1:13:28:20:1 | name0 | functions.ps1:13:28:20:1 | name1 | |
+| functions.ps1:13:28:20:1 | name1 | functions.ps1:16:24:16:24 | 0 | |
+| functions.ps1:13:28:20:1 | name2 | functions.ps1:17:24:17:29 | name1 | |
+| functions.ps1:13:28:20:1 | {...} | functions.ps1:16:24:16:24 | 0 | |
+| functions.ps1:14:5:19:18 | {...} | functions.ps1:19:5:19:18 | [Stmt] ...+... | |
+| functions.ps1:14:5:19:18 | {...} | functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | |
+| functions.ps1:16:24:16:24 | 0 | functions.ps1:13:28:20:1 | name2 | |
+| functions.ps1:16:24:16:24 | 0 | functions.ps1:17:24:17:29 | name1 | |
+| functions.ps1:17:24:17:29 | name1 | functions.ps1:17:33:17:33 | 1 | |
+| functions.ps1:17:24:17:33 | ...+... | functions.ps1:13:28:20:1 | [synth] pipeline | |
+| functions.ps1:17:24:17:33 | ...+... | functions.ps1:13:28:20:1 | name0 | |
+| functions.ps1:17:33:17:33 | 1 | functions.ps1:17:24:17:33 | ...+... | |
+| functions.ps1:19:5:19:18 | ...+... | functions.ps1:13:28:20:1 | exit {...} (normal) | |
+| functions.ps1:19:5:19:18 | [Stmt] ...+... | functions.ps1:19:13:19:18 | name2 | |
+| functions.ps1:19:5:19:18 | [Stmt] ...+... | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | functions.ps1:19:13:19:18 | name2 | |
+| functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:19:13:19:18 | name2 | functions.ps1:19:5:19:18 | ...+... | |
+| functions.ps1:22:1:34:1 | def of Add-Numbers-From-Array | functions.ps1:36:1:52:1 | def of Add-Numbers-From-Pipeline | |
+| functions.ps1:22:33:34:1 | [synth] pipeline | functions.ps1:24:5:33:8 | {...} | |
+| functions.ps1:22:33:34:1 | enter {...} | functions.ps1:22:33:34:1 | {...} | |
+| functions.ps1:22:33:34:1 | exit {...} (normal) | functions.ps1:22:33:34:1 | exit {...} | |
+| functions.ps1:22:33:34:1 | numbers | functions.ps1:22:33:34:1 | [synth] pipeline | |
+| functions.ps1:22:33:34:1 | {...} | functions.ps1:22:33:34:1 | numbers | |
+| functions.ps1:24:5:33:8 | {...} | functions.ps1:28:5:28:12 | ...=... | |
+| functions.ps1:28:5:28:8 | sum | functions.ps1:28:12:28:12 | 0 | |
+| functions.ps1:28:5:28:12 | ...=... | functions.ps1:28:5:28:8 | sum | |
+| functions.ps1:28:12:28:12 | 0 | functions.ps1:29:25:29:32 | numbers | |
+| functions.ps1:29:5:32:5 | forach(... in ...) | functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | empty |
+| functions.ps1:29:5:32:5 | forach(... in ...) | functions.ps1:33:5:33:8 | [Stmt] sum | empty |
+| functions.ps1:29:25:29:32 | numbers | functions.ps1:29:5:32:5 | forach(... in ...) | |
+| functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | functions.ps1:33:5:33:8 | sum | |
+| functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:33:5:33:8 | [Stmt] sum | functions.ps1:33:5:33:8 | sum | |
+| functions.ps1:33:5:33:8 | [Stmt] sum | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:33:5:33:8 | sum | functions.ps1:22:33:34:1 | exit {...} (normal) | |
+| functions.ps1:36:1:52:1 | def of Add-Numbers-From-Pipeline | functions.ps1:1:1:54:0 | exit {...} (normal) | |
+| functions.ps1:36:36:52:1 | [synth] pipeline | functions.ps1:41:5:43:5 | {...} | |
+| functions.ps1:36:36:52:1 | enter {...} | functions.ps1:36:36:52:1 | {...} | |
+| functions.ps1:36:36:52:1 | exit {...} (normal) | functions.ps1:36:36:52:1 | exit {...} | |
+| functions.ps1:36:36:52:1 | numbers | functions.ps1:36:36:52:1 | [synth] pipeline | |
+| functions.ps1:36:36:52:1 | {...} | functions.ps1:36:36:52:1 | numbers | |
+| functions.ps1:41:5:43:5 | {...} | functions.ps1:42:9:42:16 | ...=... | |
+| functions.ps1:42:9:42:12 | sum | functions.ps1:42:16:42:16 | 0 | |
+| functions.ps1:42:9:42:16 | ...=... | functions.ps1:42:9:42:12 | sum | |
+| functions.ps1:42:16:42:16 | 0 | functions.ps1:44:5:47:5 | {...} | |
+| functions.ps1:44:5:47:5 | {...} | functions.ps1:46:9:46:18 | ...=... | |
+| functions.ps1:46:9:46:12 | sum | functions.ps1:44:5:47:5 | {...} | |
+| functions.ps1:46:9:46:12 | sum | functions.ps1:48:5:51:5 | {...} | |
+| functions.ps1:46:9:46:18 | ...=... | functions.ps1:46:9:46:12 | sum | |
+| functions.ps1:46:17:46:18 | __pipeline_iterator | functions.ps1:1:32:9:1 | exit {...} (normal) | |
+| functions.ps1:46:17:46:18 | __pipeline_iterator | functions.ps1:13:28:20:1 | exit {...} (normal) | |
+| functions.ps1:46:17:46:18 | __pipeline_iterator | functions.ps1:22:33:34:1 | exit {...} (normal) | |
+| functions.ps1:46:17:46:18 | __pipeline_iterator | functions.ps1:36:36:52:1 | exit {...} (normal) | |
+| functions.ps1:48:5:51:5 | {...} | functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | |
+| functions.ps1:48:5:51:5 | {...} | functions.ps1:50:9:50:12 | [Stmt] sum | |
+| functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | functions.ps1:50:9:50:12 | sum | |
+| functions.ps1:50:9:50:12 | [Stmt] sum | functions.ps1:46:17:46:18 | __pipeline_iterator | |
+| functions.ps1:50:9:50:12 | [Stmt] sum | functions.ps1:50:9:50:12 | sum | |
+| functions.ps1:50:9:50:12 | sum | functions.ps1:36:36:52:1 | exit {...} (normal) | |
+| global.ps1:1:1:4:1 | {...} | global.ps1:2:5:2:10 | ...=... | |
+| global.ps1:1:1:7:1 | enter {...} | global.ps1:1:1:7:1 | {...} | |
+| global.ps1:1:1:7:1 | exit {...} (normal) | global.ps1:1:1:7:1 | exit {...} | |
+| global.ps1:1:1:7:1 | {...} | global.ps1:1:1:4:1 | {...} | |
+| global.ps1:2:5:2:6 | a | global.ps1:2:10:2:10 | 1 | |
+| global.ps1:2:5:2:10 | ...=... | global.ps1:2:5:2:6 | a | |
+| global.ps1:2:10:2:10 | 1 | global.ps1:3:5:3:10 | ...=... | |
+| global.ps1:3:5:3:6 | b | global.ps1:3:10:3:10 | 2 | |
+| global.ps1:3:5:3:10 | ...=... | global.ps1:3:5:3:6 | b | |
+| global.ps1:3:10:3:10 | 2 | global.ps1:5:1:7:1 | {...} | |
+| global.ps1:5:1:7:1 | {...} | global.ps1:6:5:6:16 | ...=... | |
+| global.ps1:6:5:6:6 | c | global.ps1:6:10:6:11 | a | |
+| global.ps1:6:5:6:16 | ...=... | global.ps1:6:5:6:6 | c | |
+| global.ps1:6:10:6:11 | a | global.ps1:6:15:6:16 | b | |
+| global.ps1:6:10:6:16 | ...+... | global.ps1:1:1:7:1 | exit {...} (normal) | |
+| global.ps1:6:15:6:16 | b | global.ps1:6:10:6:16 | ...+... | |
+| loops.ps1:1:1:7:1 | def of Test-While | loops.ps1:9:1:15:1 | def of Test-Break | |
+| loops.ps1:1:1:68:1 | {...} | loops.ps1:1:1:7:1 | def of Test-While | |
+| loops.ps1:1:1:70:0 | enter {...} | loops.ps1:1:1:70:0 | {...} | |
+| loops.ps1:1:1:70:0 | exit {...} (normal) | loops.ps1:1:1:70:0 | exit {...} | |
+| loops.ps1:1:1:70:0 | {...} | loops.ps1:1:1:68:1 | {...} | |
+| loops.ps1:1:21:7:1 | enter {...} | loops.ps1:1:21:7:1 | {...} | |
+| loops.ps1:1:21:7:1 | exit {...} (normal) | loops.ps1:1:21:7:1 | exit {...} | |
+| loops.ps1:1:21:7:1 | {...} | loops.ps1:2:5:6:5 | {...} | |
+| loops.ps1:2:5:2:6 | a | loops.ps1:2:10:2:10 | 0 | |
+| loops.ps1:2:5:2:10 | ...=... | loops.ps1:2:5:2:6 | a | |
+| loops.ps1:2:5:6:5 | {...} | loops.ps1:2:5:2:10 | ...=... | |
+| loops.ps1:2:10:2:10 | 0 | loops.ps1:4:5:6:5 | while(...) {...} | |
+| loops.ps1:4:5:6:5 | while(...) {...} | loops.ps1:4:11:4:12 | a | |
+| loops.ps1:4:11:4:12 | a | loops.ps1:4:18:4:19 | 10 | |
+| loops.ps1:4:11:4:19 | ... -le ... | loops.ps1:1:21:7:1 | exit {...} (normal) | false |
+| loops.ps1:4:11:4:19 | ... -le ... | loops.ps1:4:22:6:5 | {...} | true |
+| loops.ps1:4:18:4:19 | 10 | loops.ps1:4:11:4:19 | ... -le ... | |
+| loops.ps1:4:22:6:5 | {...} | loops.ps1:5:9:5:19 | ...=... | |
+| loops.ps1:5:9:5:10 | a | loops.ps1:5:14:5:15 | a | |
+| loops.ps1:5:9:5:19 | ...=... | loops.ps1:5:9:5:10 | a | |
+| loops.ps1:5:14:5:15 | a | loops.ps1:5:19:5:19 | 1 | |
+| loops.ps1:5:14:5:19 | ...+... | loops.ps1:4:11:4:12 | a | |
+| loops.ps1:5:19:5:19 | 1 | loops.ps1:5:14:5:19 | ...+... | |
+| loops.ps1:9:1:15:1 | def of Test-Break | loops.ps1:17:1:23:1 | def of Test-Continue | |
+| loops.ps1:9:21:15:1 | enter {...} | loops.ps1:9:21:15:1 | {...} | |
+| loops.ps1:9:21:15:1 | exit {...} (normal) | loops.ps1:9:21:15:1 | exit {...} | |
+| loops.ps1:9:21:15:1 | {...} | loops.ps1:10:5:14:5 | {...} | |
+| loops.ps1:10:5:10:6 | a | loops.ps1:10:10:10:10 | 0 | |
+| loops.ps1:10:5:10:10 | ...=... | loops.ps1:10:5:10:6 | a | |
+| loops.ps1:10:5:14:5 | {...} | loops.ps1:10:5:10:10 | ...=... | |
+| loops.ps1:10:10:10:10 | 0 | loops.ps1:11:5:14:5 | while(...) {...} | |
+| loops.ps1:11:5:14:5 | while(...) {...} | loops.ps1:11:11:11:12 | a | |
+| loops.ps1:11:11:11:12 | a | loops.ps1:11:18:11:19 | 10 | |
+| loops.ps1:11:11:11:19 | ... -le ... | loops.ps1:9:21:15:1 | exit {...} (normal) | false |
+| loops.ps1:11:11:11:19 | ... -le ... | loops.ps1:11:22:14:5 | {...} | true |
+| loops.ps1:11:18:11:19 | 10 | loops.ps1:11:11:11:19 | ... -le ... | |
+| loops.ps1:11:22:14:5 | {...} | loops.ps1:12:9:12:13 | break | |
+| loops.ps1:12:9:12:13 | break | loops.ps1:9:21:15:1 | exit {...} (normal) | break |
+| loops.ps1:17:1:23:1 | def of Test-Continue | loops.ps1:25:1:31:1 | def of Test-DoWhile | |
+| loops.ps1:17:24:23:1 | enter {...} | loops.ps1:17:24:23:1 | {...} | |
+| loops.ps1:17:24:23:1 | exit {...} (normal) | loops.ps1:17:24:23:1 | exit {...} | |
+| loops.ps1:17:24:23:1 | {...} | loops.ps1:18:5:22:5 | {...} | |
+| loops.ps1:18:5:18:6 | a | loops.ps1:18:10:18:10 | 0 | |
+| loops.ps1:18:5:18:10 | ...=... | loops.ps1:18:5:18:6 | a | |
+| loops.ps1:18:5:22:5 | {...} | loops.ps1:18:5:18:10 | ...=... | |
+| loops.ps1:18:10:18:10 | 0 | loops.ps1:19:5:22:5 | while(...) {...} | |
+| loops.ps1:19:5:22:5 | while(...) {...} | loops.ps1:19:11:19:12 | a | |
+| loops.ps1:19:11:19:12 | a | loops.ps1:19:18:19:19 | 10 | |
+| loops.ps1:19:11:19:19 | ... -le ... | loops.ps1:17:24:23:1 | exit {...} (normal) | false |
+| loops.ps1:19:11:19:19 | ... -le ... | loops.ps1:19:22:22:5 | {...} | true |
+| loops.ps1:19:18:19:19 | 10 | loops.ps1:19:11:19:19 | ... -le ... | |
+| loops.ps1:19:22:22:5 | {...} | loops.ps1:20:9:20:16 | continue | |
+| loops.ps1:20:9:20:16 | continue | loops.ps1:19:11:19:12 | a | continue |
+| loops.ps1:25:1:31:1 | def of Test-DoWhile | loops.ps1:33:1:39:1 | def of Test-DoUntil | |
+| loops.ps1:25:23:31:1 | enter {...} | loops.ps1:25:23:31:1 | {...} | |
+| loops.ps1:25:23:31:1 | exit {...} (normal) | loops.ps1:25:23:31:1 | exit {...} | |
+| loops.ps1:25:23:31:1 | {...} | loops.ps1:26:5:30:23 | {...} | |
+| loops.ps1:26:5:26:6 | a | loops.ps1:26:10:26:10 | 0 | |
+| loops.ps1:26:5:26:10 | ...=... | loops.ps1:26:5:26:6 | a | |
+| loops.ps1:26:5:30:23 | {...} | loops.ps1:26:5:26:10 | ...=... | |
+| loops.ps1:26:10:26:10 | 0 | loops.ps1:28:5:30:23 | do...while... | |
+| loops.ps1:28:5:30:23 | do...while... | loops.ps1:28:8:30:5 | {...} | |
+| loops.ps1:28:8:30:5 | {...} | loops.ps1:29:9:29:19 | ...=... | |
+| loops.ps1:29:9:29:10 | a | loops.ps1:29:14:29:15 | a | |
+| loops.ps1:29:9:29:19 | ...=... | loops.ps1:29:9:29:10 | a | |
+| loops.ps1:29:14:29:15 | a | loops.ps1:29:19:29:19 | 1 | |
+| loops.ps1:29:14:29:19 | ...+... | loops.ps1:30:14:30:15 | a | |
+| loops.ps1:29:19:29:19 | 1 | loops.ps1:29:14:29:19 | ...+... | |
+| loops.ps1:30:14:30:15 | a | loops.ps1:30:21:30:22 | 10 | |
+| loops.ps1:30:14:30:22 | ... -le ... | loops.ps1:25:23:31:1 | exit {...} (normal) | false |
+| loops.ps1:30:14:30:22 | ... -le ... | loops.ps1:28:8:30:5 | {...} | true |
+| loops.ps1:30:21:30:22 | 10 | loops.ps1:30:14:30:22 | ... -le ... | |
+| loops.ps1:33:1:39:1 | def of Test-DoUntil | loops.ps1:41:1:47:1 | def of Test-For | |
+| loops.ps1:33:23:39:1 | enter {...} | loops.ps1:33:23:39:1 | {...} | |
+| loops.ps1:33:23:39:1 | exit {...} (normal) | loops.ps1:33:23:39:1 | exit {...} | |
+| loops.ps1:33:23:39:1 | {...} | loops.ps1:34:5:38:23 | {...} | |
+| loops.ps1:34:5:34:6 | a | loops.ps1:34:10:34:10 | 0 | |
+| loops.ps1:34:5:34:10 | ...=... | loops.ps1:34:5:34:6 | a | |
+| loops.ps1:34:5:38:23 | {...} | loops.ps1:34:5:34:10 | ...=... | |
+| loops.ps1:34:10:34:10 | 0 | loops.ps1:36:5:38:23 | do...until... | |
+| loops.ps1:36:5:38:23 | do...until... | loops.ps1:36:8:38:5 | {...} | |
+| loops.ps1:36:8:38:5 | {...} | loops.ps1:37:9:37:19 | ...=... | |
+| loops.ps1:37:9:37:10 | a | loops.ps1:37:14:37:15 | a | |
+| loops.ps1:37:9:37:19 | ...=... | loops.ps1:37:9:37:10 | a | |
+| loops.ps1:37:14:37:15 | a | loops.ps1:37:19:37:19 | 1 | |
+| loops.ps1:37:14:37:19 | ...+... | loops.ps1:38:14:38:15 | a | |
+| loops.ps1:37:19:37:19 | 1 | loops.ps1:37:14:37:19 | ...+... | |
+| loops.ps1:38:14:38:15 | a | loops.ps1:38:21:38:22 | 10 | |
+| loops.ps1:38:14:38:22 | ... -ge ... | loops.ps1:33:23:39:1 | exit {...} (normal) | true |
+| loops.ps1:38:14:38:22 | ... -ge ... | loops.ps1:36:8:38:5 | {...} | false |
+| loops.ps1:38:21:38:22 | 10 | loops.ps1:38:14:38:22 | ... -ge ... | |
+| loops.ps1:41:1:47:1 | def of Test-For | loops.ps1:49:1:56:1 | def of Test-ForEach | |
+| loops.ps1:41:19:47:1 | enter {...} | loops.ps1:41:19:47:1 | {...} | |
+| loops.ps1:41:19:47:1 | exit {...} (normal) | loops.ps1:41:19:47:1 | exit {...} | |
+| loops.ps1:41:19:47:1 | {...} | loops.ps1:42:5:46:5 | {...} | |
+| loops.ps1:42:5:42:6 | a | loops.ps1:42:10:42:10 | 0 | |
+| loops.ps1:42:5:42:10 | ...=... | loops.ps1:42:5:42:6 | a | |
+| loops.ps1:42:5:46:5 | {...} | loops.ps1:42:5:42:10 | ...=... | |
+| loops.ps1:42:10:42:10 | 0 | loops.ps1:44:5:46:5 | for(...;...;...) | |
+| loops.ps1:44:5:46:5 | for(...;...;...) | loops.ps1:44:10:44:15 | ...=... | |
+| loops.ps1:44:10:44:11 | i | loops.ps1:44:15:44:15 | 0 | |
+| loops.ps1:44:10:44:15 | ...=... | loops.ps1:44:10:44:11 | i | |
+| loops.ps1:44:15:44:15 | 0 | loops.ps1:44:18:44:19 | i | |
+| loops.ps1:44:18:44:19 | i | loops.ps1:44:25:44:26 | 10 | |
+| loops.ps1:44:18:44:26 | ... -le ... | loops.ps1:41:19:47:1 | exit {...} (normal) | false |
+| loops.ps1:44:18:44:26 | ... -le ... | loops.ps1:44:42:46:5 | {...} | true |
+| loops.ps1:44:25:44:26 | 10 | loops.ps1:44:18:44:26 | ... -le ... | |
+| loops.ps1:44:29:44:30 | i | loops.ps1:44:34:44:35 | i | |
+| loops.ps1:44:29:44:39 | ...=... | loops.ps1:44:29:44:30 | i | |
+| loops.ps1:44:34:44:35 | i | loops.ps1:44:39:44:39 | 1 | |
+| loops.ps1:44:34:44:39 | ...+... | loops.ps1:44:18:44:19 | i | |
+| loops.ps1:44:39:44:39 | 1 | loops.ps1:44:34:44:39 | ...+... | |
+| loops.ps1:44:42:46:5 | {...} | loops.ps1:45:9:45:19 | ...=... | |
+| loops.ps1:45:9:45:10 | a | loops.ps1:45:14:45:15 | a | |
+| loops.ps1:45:9:45:19 | ...=... | loops.ps1:45:9:45:10 | a | |
+| loops.ps1:45:14:45:15 | a | loops.ps1:45:19:45:19 | 1 | |
+| loops.ps1:45:14:45:19 | ...+... | loops.ps1:44:18:44:19 | i | |
+| loops.ps1:45:14:45:19 | ...+... | loops.ps1:44:29:44:39 | ...=... | |
+| loops.ps1:45:19:45:19 | 1 | loops.ps1:45:14:45:19 | ...+... | |
+| loops.ps1:49:1:56:1 | def of Test-ForEach | loops.ps1:58:1:68:1 | def of Test-For-Ever | |
+| loops.ps1:49:23:56:1 | enter {...} | loops.ps1:49:23:56:1 | {...} | |
+| loops.ps1:49:23:56:1 | exit {...} (normal) | loops.ps1:49:23:56:1 | exit {...} | |
+| loops.ps1:49:23:56:1 | {...} | loops.ps1:50:5:55:5 | {...} | |
+| loops.ps1:50:5:50:16 | letterArray | loops.ps1:50:20:50:22 | a | |
+| loops.ps1:50:5:50:34 | ...=... | loops.ps1:50:5:50:16 | letterArray | |
+| loops.ps1:50:5:55:5 | {...} | loops.ps1:50:5:50:34 | ...=... | |
+| loops.ps1:50:20:50:22 | a | loops.ps1:50:24:50:26 | b | |
+| loops.ps1:50:20:50:34 | ...,... | loops.ps1:51:5:51:10 | ...=... | |
+| loops.ps1:50:24:50:26 | b | loops.ps1:50:28:50:30 | c | |
+| loops.ps1:50:28:50:30 | c | loops.ps1:50:32:50:34 | d | |
+| loops.ps1:50:32:50:34 | d | loops.ps1:50:20:50:34 | ...,... | |
+| loops.ps1:51:5:51:6 | a | loops.ps1:51:10:51:10 | 0 | |
+| loops.ps1:51:5:51:10 | ...=... | loops.ps1:51:5:51:6 | a | |
+| loops.ps1:51:10:51:10 | 0 | loops.ps1:52:25:52:36 | letterArray | |
+| loops.ps1:52:5:55:5 | forach(... in ...) | loops.ps1:49:23:56:1 | exit {...} (normal) | empty |
+| loops.ps1:52:25:52:36 | letterArray | loops.ps1:52:5:55:5 | forach(... in ...) | |
+| loops.ps1:58:1:68:1 | def of Test-For-Ever | loops.ps1:1:1:70:0 | exit {...} (normal) | |
+| loops.ps1:58:24:68:1 | enter {...} | loops.ps1:58:24:68:1 | {...} | |
+| loops.ps1:58:24:68:1 | exit {...} (normal) | loops.ps1:58:24:68:1 | exit {...} | |
+| loops.ps1:58:24:68:1 | {...} | loops.ps1:59:5:67:5 | {...} | |
+| loops.ps1:59:5:59:6 | a | loops.ps1:59:10:59:10 | 0 | |
+| loops.ps1:59:5:59:10 | ...=... | loops.ps1:59:5:59:6 | a | |
+| loops.ps1:59:5:67:5 | {...} | loops.ps1:59:5:59:10 | ...=... | |
+| loops.ps1:59:10:59:10 | 0 | loops.ps1:61:5:67:5 | for(...;...;...) | |
+| loops.ps1:61:5:67:5 | for(...;...;...) | loops.ps1:62:5:67:5 | {...} | |
+| loops.ps1:62:5:67:5 | {...} | loops.ps1:63:9:66:9 | [Stmt] if (...) {...} | |
+| loops.ps1:63:9:66:9 | [Stmt] if (...) {...} | loops.ps1:63:12:63:13 | a | |
+| loops.ps1:63:9:66:9 | if (...) {...} | loops.ps1:62:5:67:5 | {...} | |
+| loops.ps1:63:12:63:13 | a | loops.ps1:63:19:63:20 | 10 | |
+| loops.ps1:63:12:63:20 | ... -le ... | loops.ps1:63:9:66:9 | if (...) {...} | false |
+| loops.ps1:63:12:63:20 | ... -le ... | loops.ps1:64:9:66:9 | {...} | true |
+| loops.ps1:63:19:63:20 | 10 | loops.ps1:63:12:63:20 | ... -le ... | |
+| loops.ps1:64:9:66:9 | {...} | loops.ps1:65:13:65:17 | break | |
+| loops.ps1:65:13:65:17 | break | loops.ps1:58:24:68:1 | exit {...} (normal) | break |
+| try.ps1:1:1:8:1 | def of test-try-catch | try.ps1:10:1:19:1 | def of test-try-with-throw-catch | |
+| try.ps1:1:1:194:1 | enter {...} | try.ps1:1:1:194:1 | {...} | |
+| try.ps1:1:1:194:1 | exit {...} (normal) | try.ps1:1:1:194:1 | exit {...} | |
+| try.ps1:1:1:194:1 | {...} | try.ps1:1:1:8:1 | def of test-try-catch | |
+| try.ps1:1:1:194:1 | {...} | try.ps1:1:1:194:1 | {...} | |
+| try.ps1:1:25:8:1 | enter {...} | try.ps1:1:25:8:1 | {...} | |
+| try.ps1:1:25:8:1 | exit {...} (normal) | try.ps1:1:25:8:1 | exit {...} | |
+| try.ps1:1:25:8:1 | {...} | try.ps1:2:5:7:12 | {...} | |
+| try.ps1:2:5:6:5 | try {...} | try.ps1:2:9:4:5 | {...} | |
+| try.ps1:2:5:7:12 | {...} | try.ps1:2:5:6:5 | try {...} | |
+| try.ps1:2:9:4:5 | {...} | try.ps1:3:9:3:29 | [Stmt] Call to Write-Output | |
+| try.ps1:3:9:3:20 | Write-Output | try.ps1:3:22:3:29 | Hello! | |
+| try.ps1:3:9:3:29 | Call to Write-Output | try.ps1:7:5:7:12 | return ... | |
+| try.ps1:3:9:3:29 | [Stmt] Call to Write-Output | try.ps1:3:9:3:20 | Write-Output | |
+| try.ps1:3:22:3:29 | Hello! | try.ps1:3:9:3:29 | Call to Write-Output | |
+| try.ps1:7:5:7:12 | return ... | try.ps1:7:12:7:12 | 1 | |
+| try.ps1:7:12:7:12 | 1 | try.ps1:1:25:8:1 | exit {...} (normal) | |
+| try.ps1:10:1:19:1 | def of test-try-with-throw-catch | try.ps1:21:1:30:1 | def of test-try-with-throw-catch-with-throw | |
+| try.ps1:10:40:19:1 | b | try.ps1:11:5:18:12 | {...} | |
+| try.ps1:10:40:19:1 | enter {...} | try.ps1:10:40:19:1 | {...} | |
+| try.ps1:10:40:19:1 | exit {...} (normal) | try.ps1:10:40:19:1 | exit {...} | |
+| try.ps1:10:40:19:1 | {...} | try.ps1:10:40:19:1 | b | |
+| try.ps1:11:5:17:5 | try {...} | try.ps1:11:9:15:5 | {...} | |
+| try.ps1:11:5:18:12 | {...} | try.ps1:11:5:17:5 | try {...} | |
+| try.ps1:11:9:15:5 | {...} | try.ps1:12:9:14:9 | [Stmt] if (...) {...} | |
+| try.ps1:12:9:14:9 | [Stmt] if (...) {...} | try.ps1:12:12:12:13 | b | |
+| try.ps1:12:9:14:9 | if (...) {...} | try.ps1:18:5:18:12 | return ... | |
+| try.ps1:12:12:12:13 | b | try.ps1:12:9:14:9 | if (...) {...} | false |
+| try.ps1:12:12:12:13 | b | try.ps1:12:16:14:9 | {...} | true |
+| try.ps1:12:16:14:9 | {...} | try.ps1:13:13:13:20 | throw ... | |
+| try.ps1:13:13:13:20 | throw ... | try.ps1:13:19:13:20 | 42 | |
+| try.ps1:13:19:13:20 | 42 | try.ps1:12:9:14:9 | if (...) {...} | |
+| try.ps1:18:5:18:12 | return ... | try.ps1:18:12:18:12 | 1 | |
+| try.ps1:18:12:18:12 | 1 | try.ps1:10:40:19:1 | exit {...} (normal) | |
+| try.ps1:21:1:30:1 | def of test-try-with-throw-catch-with-throw | try.ps1:32:1:41:1 | def of test-try-with-throw-catch-with-rethrow | |
+| try.ps1:21:51:30:1 | b | try.ps1:22:5:29:12 | {...} | |
+| try.ps1:21:51:30:1 | enter {...} | try.ps1:21:51:30:1 | {...} | |
+| try.ps1:21:51:30:1 | exit {...} (normal) | try.ps1:21:51:30:1 | exit {...} | |
+| try.ps1:21:51:30:1 | {...} | try.ps1:21:51:30:1 | b | |
+| try.ps1:22:5:28:5 | try {...} | try.ps1:22:9:26:5 | {...} | |
+| try.ps1:22:5:29:12 | {...} | try.ps1:22:5:28:5 | try {...} | |
+| try.ps1:22:9:26:5 | {...} | try.ps1:23:9:25:9 | [Stmt] if (...) {...} | |
+| try.ps1:23:9:25:9 | [Stmt] if (...) {...} | try.ps1:23:12:23:13 | b | |
+| try.ps1:23:9:25:9 | if (...) {...} | try.ps1:29:5:29:12 | return ... | |
+| try.ps1:23:12:23:13 | b | try.ps1:23:9:25:9 | if (...) {...} | false |
+| try.ps1:23:12:23:13 | b | try.ps1:23:16:25:9 | {...} | true |
+| try.ps1:23:16:25:9 | {...} | try.ps1:24:13:24:20 | throw ... | |
+| try.ps1:24:13:24:20 | throw ... | try.ps1:24:19:24:20 | 42 | |
+| try.ps1:24:19:24:20 | 42 | try.ps1:23:9:25:9 | if (...) {...} | |
+| try.ps1:29:5:29:12 | return ... | try.ps1:29:12:29:12 | 1 | |
+| try.ps1:29:12:29:12 | 1 | try.ps1:21:51:30:1 | exit {...} (normal) | |
+| try.ps1:32:1:41:1 | def of test-try-with-throw-catch-with-rethrow | try.ps1:43:1:50:1 | def of test-try-catch-specific-1 | |
+| try.ps1:32:53:41:1 | b | try.ps1:33:5:40:12 | {...} | |
+| try.ps1:32:53:41:1 | enter {...} | try.ps1:32:53:41:1 | {...} | |
+| try.ps1:32:53:41:1 | exit {...} (normal) | try.ps1:32:53:41:1 | exit {...} | |
+| try.ps1:32:53:41:1 | {...} | try.ps1:32:53:41:1 | b | |
+| try.ps1:33:5:39:5 | try {...} | try.ps1:33:9:37:5 | {...} | |
+| try.ps1:33:5:40:12 | {...} | try.ps1:33:5:39:5 | try {...} | |
+| try.ps1:33:9:37:5 | {...} | try.ps1:34:9:36:9 | [Stmt] if (...) {...} | |
+| try.ps1:34:9:36:9 | [Stmt] if (...) {...} | try.ps1:34:12:34:13 | b | |
+| try.ps1:34:9:36:9 | if (...) {...} | try.ps1:40:5:40:12 | return ... | |
+| try.ps1:34:12:34:13 | b | try.ps1:34:9:36:9 | if (...) {...} | false |
+| try.ps1:34:12:34:13 | b | try.ps1:34:16:36:9 | {...} | true |
+| try.ps1:34:16:36:9 | {...} | try.ps1:35:13:35:20 | throw ... | |
+| try.ps1:35:13:35:20 | throw ... | try.ps1:35:19:35:20 | 42 | |
+| try.ps1:35:19:35:20 | 42 | try.ps1:34:9:36:9 | if (...) {...} | |
+| try.ps1:40:5:40:12 | return ... | try.ps1:40:12:40:12 | 1 | |
+| try.ps1:40:12:40:12 | 1 | try.ps1:32:53:41:1 | exit {...} (normal) | |
+| try.ps1:43:1:50:1 | def of test-try-catch-specific-1 | try.ps1:52:1:59:1 | def of test-try-catch-specific-1 | |
+| try.ps1:43:36:50:1 | enter {...} | try.ps1:43:36:50:1 | {...} | |
+| try.ps1:43:36:50:1 | exit {...} (normal) | try.ps1:43:36:50:1 | exit {...} | |
+| try.ps1:43:36:50:1 | {...} | try.ps1:44:5:49:12 | {...} | |
+| try.ps1:44:5:48:5 | try {...} | try.ps1:44:9:46:5 | {...} | |
+| try.ps1:44:5:49:12 | {...} | try.ps1:44:5:48:5 | try {...} | |
+| try.ps1:44:9:46:5 | {...} | try.ps1:45:9:45:29 | [Stmt] Call to Write-Output | |
+| try.ps1:45:9:45:20 | Write-Output | try.ps1:45:22:45:29 | Hello! | |
+| try.ps1:45:9:45:29 | Call to Write-Output | try.ps1:49:5:49:12 | return ... | |
+| try.ps1:45:9:45:29 | [Stmt] Call to Write-Output | try.ps1:45:9:45:20 | Write-Output | |
+| try.ps1:45:22:45:29 | Hello! | try.ps1:45:9:45:29 | Call to Write-Output | |
+| try.ps1:49:5:49:12 | return ... | try.ps1:49:12:49:12 | 1 | |
+| try.ps1:49:12:49:12 | 1 | try.ps1:43:36:50:1 | exit {...} (normal) | |
+| try.ps1:52:1:59:1 | def of test-try-catch-specific-1 | try.ps1:61:1:70:1 | def of test-try-two-catch-specific-1 | |
+| try.ps1:52:36:59:1 | enter {...} | try.ps1:52:36:59:1 | {...} | |
+| try.ps1:52:36:59:1 | exit {...} (normal) | try.ps1:52:36:59:1 | exit {...} | |
+| try.ps1:52:36:59:1 | {...} | try.ps1:53:5:58:12 | {...} | |
+| try.ps1:53:5:57:5 | try {...} | try.ps1:53:9:55:5 | {...} | |
+| try.ps1:53:5:58:12 | {...} | try.ps1:53:5:57:5 | try {...} | |
+| try.ps1:53:9:55:5 | {...} | try.ps1:54:9:54:29 | [Stmt] Call to Write-Output | |
+| try.ps1:54:9:54:20 | Write-Output | try.ps1:54:22:54:29 | Hello! | |
+| try.ps1:54:9:54:29 | Call to Write-Output | try.ps1:58:5:58:12 | return ... | |
+| try.ps1:54:9:54:29 | [Stmt] Call to Write-Output | try.ps1:54:9:54:20 | Write-Output | |
+| try.ps1:54:22:54:29 | Hello! | try.ps1:54:9:54:29 | Call to Write-Output | |
+| try.ps1:58:5:58:12 | return ... | try.ps1:58:12:58:12 | 1 | |
+| try.ps1:58:12:58:12 | 1 | try.ps1:52:36:59:1 | exit {...} (normal) | |
+| try.ps1:61:1:70:1 | def of test-try-two-catch-specific-1 | try.ps1:72:1:79:1 | def of test-try-catch-specific-2 | |
+| try.ps1:61:40:70:1 | enter {...} | try.ps1:61:40:70:1 | {...} | |
+| try.ps1:61:40:70:1 | exit {...} (normal) | try.ps1:61:40:70:1 | exit {...} | |
+| try.ps1:61:40:70:1 | {...} | try.ps1:62:5:69:12 | {...} | |
+| try.ps1:62:5:68:5 | try {...} | try.ps1:62:9:64:5 | {...} | |
+| try.ps1:62:5:69:12 | {...} | try.ps1:62:5:68:5 | try {...} | |
+| try.ps1:62:9:64:5 | {...} | try.ps1:63:9:63:29 | [Stmt] Call to Write-Output | |
+| try.ps1:63:9:63:20 | Write-Output | try.ps1:63:22:63:29 | Hello! | |
+| try.ps1:63:9:63:29 | Call to Write-Output | try.ps1:69:5:69:12 | return ... | |
+| try.ps1:63:9:63:29 | [Stmt] Call to Write-Output | try.ps1:63:9:63:20 | Write-Output | |
+| try.ps1:63:22:63:29 | Hello! | try.ps1:63:9:63:29 | Call to Write-Output | |
+| try.ps1:69:5:69:12 | return ... | try.ps1:69:12:69:12 | 2 | |
+| try.ps1:69:12:69:12 | 2 | try.ps1:61:40:70:1 | exit {...} (normal) | |
+| try.ps1:72:1:79:1 | def of test-try-catch-specific-2 | try.ps1:81:1:90:1 | def of test-try-two-catch-specific-2 | |
+| try.ps1:72:36:79:1 | enter {...} | try.ps1:72:36:79:1 | {...} | |
+| try.ps1:72:36:79:1 | exit {...} (normal) | try.ps1:72:36:79:1 | exit {...} | |
+| try.ps1:72:36:79:1 | {...} | try.ps1:73:5:78:12 | {...} | |
+| try.ps1:73:5:77:5 | try {...} | try.ps1:73:9:75:5 | {...} | |
+| try.ps1:73:5:78:12 | {...} | try.ps1:73:5:77:5 | try {...} | |
+| try.ps1:73:9:75:5 | {...} | try.ps1:74:9:74:29 | [Stmt] Call to Write-Output | |
+| try.ps1:74:9:74:20 | Write-Output | try.ps1:74:22:74:29 | Hello! | |
+| try.ps1:74:9:74:29 | Call to Write-Output | try.ps1:78:5:78:12 | return ... | |
+| try.ps1:74:9:74:29 | [Stmt] Call to Write-Output | try.ps1:74:9:74:20 | Write-Output | |
+| try.ps1:74:22:74:29 | Hello! | try.ps1:74:9:74:29 | Call to Write-Output | |
+| try.ps1:78:5:78:12 | return ... | try.ps1:78:12:78:12 | 1 | |
+| try.ps1:78:12:78:12 | 1 | try.ps1:72:36:79:1 | exit {...} (normal) | |
+| try.ps1:81:1:90:1 | def of test-try-two-catch-specific-2 | try.ps1:92:1:103:1 | def of test-try-three-catch-specific-2 | |
+| try.ps1:81:40:90:1 | enter {...} | try.ps1:81:40:90:1 | {...} | |
+| try.ps1:81:40:90:1 | exit {...} (normal) | try.ps1:81:40:90:1 | exit {...} | |
+| try.ps1:81:40:90:1 | {...} | try.ps1:82:5:89:12 | {...} | |
+| try.ps1:82:5:88:5 | try {...} | try.ps1:82:9:84:5 | {...} | |
+| try.ps1:82:5:89:12 | {...} | try.ps1:82:5:88:5 | try {...} | |
+| try.ps1:82:9:84:5 | {...} | try.ps1:83:9:83:29 | [Stmt] Call to Write-Output | |
+| try.ps1:83:9:83:20 | Write-Output | try.ps1:83:22:83:29 | Hello! | |
+| try.ps1:83:9:83:29 | Call to Write-Output | try.ps1:89:5:89:12 | return ... | |
+| try.ps1:83:9:83:29 | [Stmt] Call to Write-Output | try.ps1:83:9:83:20 | Write-Output | |
+| try.ps1:83:22:83:29 | Hello! | try.ps1:83:9:83:29 | Call to Write-Output | |
+| try.ps1:89:5:89:12 | return ... | try.ps1:89:12:89:12 | 2 | |
+| try.ps1:89:12:89:12 | 2 | try.ps1:81:40:90:1 | exit {...} (normal) | |
+| try.ps1:92:1:103:1 | def of test-try-three-catch-specific-2 | try.ps1:105:1:114:1 | def of test-try-catch-finally | |
+| try.ps1:92:42:103:1 | enter {...} | try.ps1:92:42:103:1 | {...} | |
+| try.ps1:92:42:103:1 | exit {...} (normal) | try.ps1:92:42:103:1 | exit {...} | |
+| try.ps1:92:42:103:1 | {...} | try.ps1:93:5:102:12 | {...} | |
+| try.ps1:93:5:101:5 | try {...} | try.ps1:93:9:95:5 | {...} | |
+| try.ps1:93:5:102:12 | {...} | try.ps1:93:5:101:5 | try {...} | |
+| try.ps1:93:9:95:5 | {...} | try.ps1:94:9:94:29 | [Stmt] Call to Write-Output | |
+| try.ps1:94:9:94:20 | Write-Output | try.ps1:94:22:94:29 | Hello! | |
+| try.ps1:94:9:94:29 | Call to Write-Output | try.ps1:102:5:102:12 | return ... | |
+| try.ps1:94:9:94:29 | [Stmt] Call to Write-Output | try.ps1:94:9:94:20 | Write-Output | |
+| try.ps1:94:22:94:29 | Hello! | try.ps1:94:9:94:29 | Call to Write-Output | |
+| try.ps1:102:5:102:12 | return ... | try.ps1:102:12:102:12 | 3 | |
+| try.ps1:102:12:102:12 | 3 | try.ps1:92:42:103:1 | exit {...} (normal) | |
+| try.ps1:105:1:114:1 | def of test-try-catch-finally | try.ps1:116:1:123:1 | def of test-try-finally | |
+| try.ps1:105:33:114:1 | enter {...} | try.ps1:105:33:114:1 | {...} | |
+| try.ps1:105:33:114:1 | exit {...} (normal) | try.ps1:105:33:114:1 | exit {...} | |
+| try.ps1:105:33:114:1 | {...} | try.ps1:106:5:113:12 | {...} | |
+| try.ps1:106:5:112:5 | try {...} | try.ps1:106:9:108:5 | {...} | |
+| try.ps1:106:5:113:12 | {...} | try.ps1:106:5:112:5 | try {...} | |
+| try.ps1:106:9:108:5 | {...} | try.ps1:107:9:107:29 | [Stmt] Call to Write-Output | |
+| try.ps1:107:9:107:20 | Write-Output | try.ps1:107:22:107:29 | Hello! | |
+| try.ps1:107:9:107:29 | Call to Write-Output | try.ps1:110:15:112:5 | {...} | |
+| try.ps1:107:9:107:29 | [Stmt] Call to Write-Output | try.ps1:107:9:107:20 | Write-Output | |
+| try.ps1:107:22:107:29 | Hello! | try.ps1:107:9:107:29 | Call to Write-Output | |
+| try.ps1:110:15:112:5 | {...} | try.ps1:111:9:111:31 | [Stmt] Call to Write-Output | |
+| try.ps1:111:9:111:20 | Write-Output | try.ps1:111:22:111:31 | Finally! | |
+| try.ps1:111:9:111:31 | Call to Write-Output | try.ps1:113:5:113:12 | return ... | |
+| try.ps1:111:9:111:31 | [Stmt] Call to Write-Output | try.ps1:111:9:111:20 | Write-Output | |
+| try.ps1:111:22:111:31 | Finally! | try.ps1:111:9:111:31 | Call to Write-Output | |
+| try.ps1:113:5:113:12 | return ... | try.ps1:113:12:113:12 | 1 | |
+| try.ps1:113:12:113:12 | 1 | try.ps1:105:33:114:1 | exit {...} (normal) | |
+| try.ps1:116:1:123:1 | def of test-try-finally | try.ps1:125:1:134:1 | def of test-try-finally-catch-specific-1 | |
+| try.ps1:116:27:123:1 | enter {...} | try.ps1:116:27:123:1 | {...} | |
+| try.ps1:116:27:123:1 | exit {...} (normal) | try.ps1:116:27:123:1 | exit {...} | |
+| try.ps1:116:27:123:1 | {...} | try.ps1:117:5:122:12 | {...} | |
+| try.ps1:117:5:121:5 | try {...} | try.ps1:117:9:119:5 | {...} | |
+| try.ps1:117:5:122:12 | {...} | try.ps1:117:5:121:5 | try {...} | |
+| try.ps1:117:9:119:5 | {...} | try.ps1:118:9:118:29 | [Stmt] Call to Write-Output | |
+| try.ps1:118:9:118:20 | Write-Output | try.ps1:118:22:118:29 | Hello! | |
+| try.ps1:118:9:118:29 | Call to Write-Output | try.ps1:119:15:121:5 | {...} | |
+| try.ps1:118:9:118:29 | [Stmt] Call to Write-Output | try.ps1:118:9:118:20 | Write-Output | |
+| try.ps1:118:22:118:29 | Hello! | try.ps1:118:9:118:29 | Call to Write-Output | |
+| try.ps1:119:15:121:5 | {...} | try.ps1:120:9:120:31 | [Stmt] Call to Write-Output | |
+| try.ps1:120:9:120:20 | Write-Output | try.ps1:120:22:120:31 | Finally! | |
+| try.ps1:120:9:120:31 | Call to Write-Output | try.ps1:122:5:122:12 | return ... | |
+| try.ps1:120:9:120:31 | [Stmt] Call to Write-Output | try.ps1:120:9:120:20 | Write-Output | |
+| try.ps1:120:22:120:31 | Finally! | try.ps1:120:9:120:31 | Call to Write-Output | |
+| try.ps1:122:5:122:12 | return ... | try.ps1:122:12:122:12 | 1 | |
+| try.ps1:122:12:122:12 | 1 | try.ps1:116:27:123:1 | exit {...} (normal) | |
+| try.ps1:125:1:134:1 | def of test-try-finally-catch-specific-1 | try.ps1:136:1:147:1 | def of test-nested-try-inner-finally | |
+| try.ps1:125:44:134:1 | enter {...} | try.ps1:125:44:134:1 | {...} | |
+| try.ps1:125:44:134:1 | exit {...} (normal) | try.ps1:125:44:134:1 | exit {...} | |
+| try.ps1:125:44:134:1 | {...} | try.ps1:126:5:133:12 | {...} | |
+| try.ps1:126:5:132:5 | try {...} | try.ps1:126:9:128:5 | {...} | |
+| try.ps1:126:5:133:12 | {...} | try.ps1:126:5:132:5 | try {...} | |
+| try.ps1:126:9:128:5 | {...} | try.ps1:127:9:127:29 | [Stmt] Call to Write-Output | |
+| try.ps1:127:9:127:20 | Write-Output | try.ps1:127:22:127:29 | Hello! | |
+| try.ps1:127:9:127:29 | Call to Write-Output | try.ps1:130:15:132:5 | {...} | |
+| try.ps1:127:9:127:29 | [Stmt] Call to Write-Output | try.ps1:127:9:127:20 | Write-Output | |
+| try.ps1:127:22:127:29 | Hello! | try.ps1:127:9:127:29 | Call to Write-Output | |
+| try.ps1:130:15:132:5 | {...} | try.ps1:131:9:131:31 | [Stmt] Call to Write-Output | |
+| try.ps1:131:9:131:20 | Write-Output | try.ps1:131:22:131:31 | Finally! | |
+| try.ps1:131:9:131:31 | Call to Write-Output | try.ps1:133:5:133:12 | return ... | |
+| try.ps1:131:9:131:31 | [Stmt] Call to Write-Output | try.ps1:131:9:131:20 | Write-Output | |
+| try.ps1:131:22:131:31 | Finally! | try.ps1:131:9:131:31 | Call to Write-Output | |
+| try.ps1:133:5:133:12 | return ... | try.ps1:133:12:133:12 | 1 | |
+| try.ps1:133:12:133:12 | 1 | try.ps1:125:44:134:1 | exit {...} (normal) | |
+| try.ps1:136:1:147:1 | def of test-nested-try-inner-finally | try.ps1:149:1:162:1 | def of test-nested-try-inner-finally | |
+| try.ps1:136:40:147:1 | enter {...} | try.ps1:136:40:147:1 | {...} | |
+| try.ps1:136:40:147:1 | exit {...} (normal) | try.ps1:136:40:147:1 | exit {...} | |
+| try.ps1:136:40:147:1 | {...} | try.ps1:137:5:146:12 | {...} | |
+| try.ps1:137:5:145:5 | try {...} | try.ps1:137:9:143:5 | {...} | |
+| try.ps1:137:5:146:12 | {...} | try.ps1:137:5:145:5 | try {...} | |
+| try.ps1:137:9:143:5 | {...} | try.ps1:138:9:142:9 | try {...} | |
+| try.ps1:138:9:142:9 | try {...} | try.ps1:138:13:140:9 | {...} | |
+| try.ps1:138:13:140:9 | {...} | try.ps1:139:13:139:33 | [Stmt] Call to Write-Output | |
+| try.ps1:139:13:139:24 | Write-Output | try.ps1:139:26:139:33 | Hello! | |
+| try.ps1:139:13:139:33 | Call to Write-Output | try.ps1:146:5:146:12 | return ... | |
+| try.ps1:139:13:139:33 | [Stmt] Call to Write-Output | try.ps1:139:13:139:24 | Write-Output | |
+| try.ps1:139:26:139:33 | Hello! | try.ps1:139:13:139:33 | Call to Write-Output | |
+| try.ps1:146:5:146:12 | return ... | try.ps1:146:12:146:12 | 1 | |
+| try.ps1:146:12:146:12 | 1 | try.ps1:136:40:147:1 | exit {...} (normal) | |
+| try.ps1:149:1:162:1 | def of test-nested-try-inner-finally | try.ps1:164:1:177:1 | def of test-nested-try-outer-finally | |
+| try.ps1:149:40:162:1 | enter {...} | try.ps1:149:40:162:1 | {...} | |
+| try.ps1:149:40:162:1 | exit {...} (normal) | try.ps1:149:40:162:1 | exit {...} | |
+| try.ps1:149:40:162:1 | {...} | try.ps1:150:5:161:12 | {...} | |
+| try.ps1:150:5:160:5 | try {...} | try.ps1:150:9:158:5 | {...} | |
+| try.ps1:150:5:161:12 | {...} | try.ps1:150:5:160:5 | try {...} | |
+| try.ps1:150:9:158:5 | {...} | try.ps1:151:9:157:9 | try {...} | |
+| try.ps1:151:9:157:9 | try {...} | try.ps1:151:13:153:9 | {...} | |
+| try.ps1:151:13:153:9 | {...} | try.ps1:152:13:152:33 | [Stmt] Call to Write-Output | |
+| try.ps1:152:13:152:24 | Write-Output | try.ps1:152:26:152:33 | Hello! | |
+| try.ps1:152:13:152:33 | Call to Write-Output | try.ps1:155:19:157:9 | {...} | |
+| try.ps1:152:13:152:33 | [Stmt] Call to Write-Output | try.ps1:152:13:152:24 | Write-Output | |
+| try.ps1:152:26:152:33 | Hello! | try.ps1:152:13:152:33 | Call to Write-Output | |
+| try.ps1:155:19:157:9 | {...} | try.ps1:156:13:156:35 | [Stmt] Call to Write-Output | |
+| try.ps1:156:13:156:24 | Write-Output | try.ps1:156:26:156:35 | Finally! | |
+| try.ps1:156:13:156:35 | Call to Write-Output | try.ps1:161:5:161:12 | return ... | |
+| try.ps1:156:13:156:35 | [Stmt] Call to Write-Output | try.ps1:156:13:156:24 | Write-Output | |
+| try.ps1:156:26:156:35 | Finally! | try.ps1:156:13:156:35 | Call to Write-Output | |
+| try.ps1:161:5:161:12 | return ... | try.ps1:161:12:161:12 | 1 | |
+| try.ps1:161:12:161:12 | 1 | try.ps1:149:40:162:1 | exit {...} (normal) | |
+| try.ps1:164:1:177:1 | def of test-nested-try-outer-finally | try.ps1:179:1:194:1 | def of test-nested-try-inner-outer-finally | |
+| try.ps1:164:40:177:1 | enter {...} | try.ps1:164:40:177:1 | {...} | |
+| try.ps1:164:40:177:1 | exit {...} (normal) | try.ps1:164:40:177:1 | exit {...} | |
+| try.ps1:164:40:177:1 | {...} | try.ps1:165:5:176:12 | {...} | |
+| try.ps1:165:5:175:5 | try {...} | try.ps1:165:9:171:5 | {...} | |
+| try.ps1:165:5:176:12 | {...} | try.ps1:165:5:175:5 | try {...} | |
+| try.ps1:165:9:171:5 | {...} | try.ps1:166:9:170:9 | try {...} | |
+| try.ps1:166:9:170:9 | try {...} | try.ps1:166:13:168:9 | {...} | |
+| try.ps1:166:13:168:9 | {...} | try.ps1:167:13:167:33 | [Stmt] Call to Write-Output | |
+| try.ps1:167:13:167:24 | Write-Output | try.ps1:167:26:167:33 | Hello! | |
+| try.ps1:167:13:167:33 | Call to Write-Output | try.ps1:173:15:175:5 | {...} | |
+| try.ps1:167:13:167:33 | [Stmt] Call to Write-Output | try.ps1:167:13:167:24 | Write-Output | |
+| try.ps1:167:26:167:33 | Hello! | try.ps1:167:13:167:33 | Call to Write-Output | |
+| try.ps1:173:15:175:5 | {...} | try.ps1:174:9:174:31 | [Stmt] Call to Write-Output | |
+| try.ps1:174:9:174:20 | Write-Output | try.ps1:174:22:174:31 | Finally! | |
+| try.ps1:174:9:174:31 | Call to Write-Output | try.ps1:176:5:176:12 | return ... | |
+| try.ps1:174:9:174:31 | [Stmt] Call to Write-Output | try.ps1:174:9:174:20 | Write-Output | |
+| try.ps1:174:22:174:31 | Finally! | try.ps1:174:9:174:31 | Call to Write-Output | |
+| try.ps1:176:5:176:12 | return ... | try.ps1:176:12:176:12 | 1 | |
+| try.ps1:176:12:176:12 | 1 | try.ps1:164:40:177:1 | exit {...} (normal) | |
+| try.ps1:179:1:194:1 | def of test-nested-try-inner-outer-finally | try.ps1:1:1:194:1 | exit {...} (normal) | |
+| try.ps1:179:46:194:1 | enter {...} | try.ps1:179:46:194:1 | {...} | |
+| try.ps1:179:46:194:1 | exit {...} (normal) | try.ps1:179:46:194:1 | exit {...} | |
+| try.ps1:179:46:194:1 | {...} | try.ps1:180:5:193:12 | {...} | |
+| try.ps1:180:5:192:5 | try {...} | try.ps1:180:9:188:5 | {...} | |
+| try.ps1:180:5:193:12 | {...} | try.ps1:180:5:192:5 | try {...} | |
+| try.ps1:180:9:188:5 | {...} | try.ps1:181:9:187:9 | try {...} | |
+| try.ps1:181:9:187:9 | try {...} | try.ps1:181:13:183:9 | {...} | |
+| try.ps1:181:13:183:9 | {...} | try.ps1:182:13:182:33 | [Stmt] Call to Write-Output | |
+| try.ps1:182:13:182:24 | Write-Output | try.ps1:182:26:182:33 | Hello! | |
+| try.ps1:182:13:182:33 | Call to Write-Output | try.ps1:185:19:187:9 | {...} | |
+| try.ps1:182:13:182:33 | [Stmt] Call to Write-Output | try.ps1:182:13:182:24 | Write-Output | |
+| try.ps1:182:26:182:33 | Hello! | try.ps1:182:13:182:33 | Call to Write-Output | |
+| try.ps1:185:19:187:9 | {...} | try.ps1:186:13:186:35 | [Stmt] Call to Write-Output | |
+| try.ps1:186:13:186:24 | Write-Output | try.ps1:186:26:186:35 | Finally! | |
+| try.ps1:186:13:186:35 | Call to Write-Output | try.ps1:190:15:192:5 | {...} | |
+| try.ps1:186:13:186:35 | [Stmt] Call to Write-Output | try.ps1:186:13:186:24 | Write-Output | |
+| try.ps1:186:26:186:35 | Finally! | try.ps1:186:13:186:35 | Call to Write-Output | |
+| try.ps1:190:15:192:5 | {...} | try.ps1:191:9:191:31 | [Stmt] Call to Write-Output | |
+| try.ps1:191:9:191:20 | Write-Output | try.ps1:191:22:191:31 | Finally! | |
+| try.ps1:191:9:191:31 | Call to Write-Output | try.ps1:193:5:193:12 | return ... | |
+| try.ps1:191:9:191:31 | [Stmt] Call to Write-Output | try.ps1:191:9:191:20 | Write-Output | |
+| try.ps1:191:22:191:31 | Finally! | try.ps1:191:9:191:31 | Call to Write-Output | |
+| try.ps1:193:5:193:12 | return ... | try.ps1:193:12:193:12 | 1 | |
+| try.ps1:193:12:193:12 | 1 | try.ps1:179:46:194:1 | exit {...} (normal) | |
diff --git a/powershell/ql/test/library-tests/controlflow/graph/consistency.expected b/powershell/ql/test/library-tests/controlflow/graph/consistency.expected
new file mode 100644
index 000000000000..68e5304a2904
--- /dev/null
+++ b/powershell/ql/test/library-tests/controlflow/graph/consistency.expected
@@ -0,0 +1,44 @@
+nonUniqueSetRepresentation
+breakInvariant2
+breakInvariant3
+breakInvariant4
+breakInvariant5
+multipleSuccessors
+| functions.ps1:8:5:8:23 | [Stmt] ...+... | successor | functions.ps1:8:5:8:12 | number1 |
+| functions.ps1:8:5:8:23 | [Stmt] ...+... | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | successor | functions.ps1:8:5:8:12 | number1 |
+| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:16:24:16:24 | 0 | successor | functions.ps1:13:28:20:1 | name2 |
+| functions.ps1:16:24:16:24 | 0 | successor | functions.ps1:17:24:17:29 | name1 |
+| functions.ps1:17:24:17:33 | ...+... | successor | functions.ps1:13:28:20:1 | [synth] pipeline |
+| functions.ps1:17:24:17:33 | ...+... | successor | functions.ps1:13:28:20:1 | name0 |
+| functions.ps1:19:5:19:18 | [Stmt] ...+... | successor | functions.ps1:19:13:19:18 | name2 |
+| functions.ps1:19:5:19:18 | [Stmt] ...+... | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | successor | functions.ps1:19:13:19:18 | name2 |
+| functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | successor | functions.ps1:33:5:33:8 | sum |
+| functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:33:5:33:8 | [Stmt] sum | successor | functions.ps1:33:5:33:8 | sum |
+| functions.ps1:33:5:33:8 | [Stmt] sum | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:46:9:46:12 | sum | successor | functions.ps1:44:5:47:5 | {...} |
+| functions.ps1:46:9:46:12 | sum | successor | functions.ps1:48:5:51:5 | {...} |
+| functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | successor | functions.ps1:50:9:50:12 | sum |
+| functions.ps1:50:9:50:12 | [Stmt] sum | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
+| functions.ps1:50:9:50:12 | [Stmt] sum | successor | functions.ps1:50:9:50:12 | sum |
+| loops.ps1:45:14:45:19 | ...+... | successor | loops.ps1:44:18:44:19 | i |
+| loops.ps1:45:14:45:19 | ...+... | successor | loops.ps1:44:29:44:39 | ...=... |
+simpleAndNormalSuccessors
+deadEnd
+nonUniqueSplitKind
+nonUniqueListOrder
+multipleToString
+| functions.ps1:8:5:8:23 | [Stmt] ...+... | [Stmt] ...+...,[Stmt] __pipeline_iterator |
+| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | [Stmt] ...+...,[Stmt] __pipeline_iterator |
+| functions.ps1:19:5:19:18 | [Stmt] ...+... | [Stmt] ...+...,[Stmt] __pipeline_iterator |
+| functions.ps1:19:5:19:18 | [Stmt] __pipeline_iterator | [Stmt] ...+...,[Stmt] __pipeline_iterator |
+| functions.ps1:33:5:33:8 | [Stmt] __pipeline_iterator | [Stmt] __pipeline_iterator,[Stmt] sum |
+| functions.ps1:33:5:33:8 | [Stmt] sum | [Stmt] __pipeline_iterator,[Stmt] sum |
+| functions.ps1:50:9:50:12 | [Stmt] __pipeline_iterator | [Stmt] __pipeline_iterator,[Stmt] sum |
+| functions.ps1:50:9:50:12 | [Stmt] sum | [Stmt] __pipeline_iterator,[Stmt] sum |
+scopeNoFirst
diff --git a/powershell/ql/test/library-tests/controlflow/graph/consistency.ql b/powershell/ql/test/library-tests/controlflow/graph/consistency.ql
new file mode 100644
index 000000000000..f7ab51cc4941
--- /dev/null
+++ b/powershell/ql/test/library-tests/controlflow/graph/consistency.ql
@@ -0,0 +1 @@
+import semmle.code.powershell.controlflow.internal.ControlFlowGraphImpl::Consistency
\ No newline at end of file
diff --git a/powershell/ql/test/library-tests/dataflow/fields/test.expected b/powershell/ql/test/library-tests/dataflow/fields/test.expected
index 40cc3128e6a9..8916976e2a57 100644
--- a/powershell/ql/test/library-tests/dataflow/fields/test.expected
+++ b/powershell/ql/test/library-tests/dataflow/fields/test.expected
@@ -1,214 +1,139 @@
models
edges
-| test.ps1:1:1:1:3 | [post] a [f] | test.ps1:2:6:2:8 | a [f] | provenance | |
-| test.ps1:1:8:1:18 | call to Source | test.ps1:1:1:1:3 | [post] a [f] | provenance | |
-| test.ps1:2:6:2:8 | a [f] | test.ps1:2:6:2:10 | f | provenance | |
-| test.ps1:8:1:8:6 | [post] arr1 [element 3] | test.ps1:9:6:9:11 | arr1 [element 3] | provenance | |
-| test.ps1:8:1:8:6 | [post] arr1 [element 3] | test.ps1:9:6:9:11 | arr1 [element 3] | provenance | |
-| test.ps1:8:12:8:22 | call to Source | test.ps1:8:1:8:6 | [post] arr1 [element 3] | provenance | |
-| test.ps1:8:12:8:22 | call to Source | test.ps1:8:1:8:6 | [post] arr1 [element 3] | provenance | |
-| test.ps1:9:6:9:11 | arr1 [element 3] | test.ps1:9:6:9:14 | ...[...] | provenance | |
-| test.ps1:9:6:9:11 | arr1 [element 3] | test.ps1:9:6:9:14 | ...[...] | provenance | |
-| test.ps1:12:1:12:6 | [post] arr2 [element] | test.ps1:13:6:13:11 | arr2 [element] | provenance | |
-| test.ps1:12:19:12:29 | call to Source | test.ps1:12:1:12:6 | [post] arr2 [element] | provenance | |
-| test.ps1:13:6:13:11 | arr2 [element] | test.ps1:13:6:13:14 | ...[...] | provenance | |
-| test.ps1:15:1:15:6 | [post] arr3 [element 3] | test.ps1:16:6:16:11 | arr3 [element 3] | provenance | |
-| test.ps1:15:1:15:6 | [post] arr3 [element 3] | test.ps1:16:6:16:11 | arr3 [element 3] | provenance | |
-| test.ps1:15:12:15:22 | call to Source | test.ps1:15:1:15:6 | [post] arr3 [element 3] | provenance | |
-| test.ps1:15:12:15:22 | call to Source | test.ps1:15:1:15:6 | [post] arr3 [element 3] | provenance | |
-| test.ps1:16:6:16:11 | arr3 [element 3] | test.ps1:16:6:16:21 | ...[...] | provenance | |
-| test.ps1:16:6:16:11 | arr3 [element 3] | test.ps1:16:6:16:21 | ...[...] | provenance | |
-| test.ps1:18:1:18:6 | [post] arr4 [element] | test.ps1:19:6:19:11 | arr4 [element] | provenance | |
-| test.ps1:18:20:18:30 | call to Source | test.ps1:18:1:18:6 | [post] arr4 [element] | provenance | |
-| test.ps1:19:6:19:11 | arr4 [element] | test.ps1:19:6:19:22 | ...[...] | provenance | |
-| test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | test.ps1:22:6:22:11 | arr5 [element, element 1] | provenance | |
-| test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | test.ps1:22:6:22:11 | arr5 [element, element 1] | provenance | |
-| test.ps1:21:1:21:17 | [post] ...[...] [element 1] | test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | provenance | |
-| test.ps1:21:1:21:17 | [post] ...[...] [element 1] | test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | provenance | |
-| test.ps1:21:23:21:33 | call to Source | test.ps1:21:1:21:17 | [post] ...[...] [element 1] | provenance | |
-| test.ps1:21:23:21:33 | call to Source | test.ps1:21:1:21:17 | [post] ...[...] [element 1] | provenance | |
-| test.ps1:22:6:22:11 | arr5 [element, element 1] | test.ps1:22:6:22:22 | ...[...] [element 1] | provenance | |
-| test.ps1:22:6:22:11 | arr5 [element, element 1] | test.ps1:22:6:22:22 | ...[...] [element 1] | provenance | |
-| test.ps1:22:6:22:22 | ...[...] [element 1] | test.ps1:22:6:22:25 | ...[...] | provenance | |
-| test.ps1:22:6:22:22 | ...[...] [element 1] | test.ps1:22:6:22:25 | ...[...] | provenance | |
-| test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | test.ps1:26:6:26:11 | arr6 [element 1, element] | provenance | |
-| test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | test.ps1:26:6:26:11 | arr6 [element 1, element] | provenance | |
-| test.ps1:25:1:25:9 | [post] ...[...] [element] | test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | provenance | |
-| test.ps1:25:1:25:9 | [post] ...[...] [element] | test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | provenance | |
-| test.ps1:25:23:25:33 | call to Source | test.ps1:25:1:25:9 | [post] ...[...] [element] | provenance | |
-| test.ps1:26:6:26:11 | arr6 [element 1, element] | test.ps1:26:6:26:14 | ...[...] [element] | provenance | |
-| test.ps1:26:6:26:11 | arr6 [element 1, element] | test.ps1:26:6:26:14 | ...[...] [element] | provenance | |
-| test.ps1:26:6:26:14 | ...[...] [element] | test.ps1:26:6:26:25 | ...[...] | provenance | |
-| test.ps1:29:1:29:6 | [post] arr7 [element, element] | test.ps1:30:6:30:11 | arr7 [element, element] | provenance | |
-| test.ps1:29:1:29:6 | [post] arr7 [element, element] | test.ps1:31:6:31:11 | arr7 [element, element] | provenance | |
-| test.ps1:29:1:29:17 | [post] ...[...] [element] | test.ps1:29:1:29:6 | [post] arr7 [element, element] | provenance | |
-| test.ps1:29:31:29:41 | call to Source | test.ps1:29:1:29:17 | [post] ...[...] [element] | provenance | |
-| test.ps1:30:6:30:11 | arr7 [element, element] | test.ps1:30:6:30:14 | ...[...] [element] | provenance | |
-| test.ps1:30:6:30:14 | ...[...] [element] | test.ps1:30:6:30:17 | ...[...] | provenance | |
-| test.ps1:31:6:31:11 | arr7 [element, element] | test.ps1:31:6:31:22 | ...[...] [element] | provenance | |
-| test.ps1:31:6:31:22 | ...[...] [element] | test.ps1:31:6:31:33 | ...[...] | provenance | |
-| test.ps1:33:6:33:17 | call to Source | test.ps1:35:15:35:17 | x | provenance | |
-| test.ps1:35:9:35:17 | ...,... [element 2] | test.ps1:38:6:38:11 | arr8 [element 2] | provenance | |
-| test.ps1:35:9:35:17 | ...,... [element 2] | test.ps1:39:6:39:11 | arr8 [element 2] | provenance | |
-| test.ps1:35:15:35:17 | x | test.ps1:35:9:35:17 | ...,... [element 2] | provenance | |
-| test.ps1:38:6:38:11 | arr8 [element 2] | test.ps1:38:6:38:14 | ...[...] | provenance | |
-| test.ps1:39:6:39:11 | arr8 [element 2] | test.ps1:39:6:39:21 | ...[...] | provenance | |
-| test.ps1:41:6:41:17 | call to Source | test.ps1:43:17:43:19 | y | provenance | |
-| test.ps1:43:11:43:19 | ...,... [element 2] | test.ps1:46:6:46:11 | arr9 [element 2] | provenance | |
-| test.ps1:43:11:43:19 | ...,... [element 2] | test.ps1:47:6:47:11 | arr9 [element 2] | provenance | |
-| test.ps1:43:17:43:19 | y | test.ps1:43:11:43:19 | ...,... [element 2] | provenance | |
-| test.ps1:46:6:46:11 | arr9 [element 2] | test.ps1:46:6:46:14 | ...[...] | provenance | |
-| test.ps1:47:6:47:11 | arr9 [element 2] | test.ps1:47:6:47:21 | ...[...] | provenance | |
-| test.ps1:52:22:54:6 | this [field] | test.ps1:53:14:53:19 | this [field] | provenance | |
-| test.ps1:53:14:53:19 | this [field] | test.ps1:53:14:53:25 | field | provenance | |
-| test.ps1:59:1:59:9 | [post] myClass [field] | test.ps1:61:1:61:9 | myClass [field] | provenance | |
-| test.ps1:59:18:59:29 | call to Source | test.ps1:59:1:59:9 | [post] myClass [field] | provenance | |
-| test.ps1:61:1:61:9 | myClass [field] | test.ps1:52:22:54:6 | this [field] | provenance | |
-| test.ps1:64:10:64:21 | call to Source | test.ps1:67:5:67:7 | x | provenance | |
-| test.ps1:65:10:65:21 | call to Source | test.ps1:68:5:68:7 | y | provenance | |
-| test.ps1:66:10:66:21 | call to Source | test.ps1:68:9:68:11 | z | provenance | |
-| test.ps1:67:5:67:7 | x | test.ps1:71:6:71:13 | call to produce [element] | provenance | |
-| test.ps1:68:5:68:7 | y | test.ps1:68:5:68:11 | ...,... [element 0] | provenance | |
-| test.ps1:68:5:68:11 | ...,... [element 0] | test.ps1:71:6:71:13 | call to produce [element] | provenance | |
-| test.ps1:68:5:68:11 | ...,... [element 1] | test.ps1:71:6:71:13 | call to produce [element] | provenance | |
-| test.ps1:68:9:68:11 | z | test.ps1:68:5:68:11 | ...,... [element 1] | provenance | |
-| test.ps1:71:6:71:13 | call to produce [element] | test.ps1:72:6:72:8 | x [element] | provenance | |
-| test.ps1:71:6:71:13 | call to produce [element] | test.ps1:73:6:73:8 | x [element] | provenance | |
-| test.ps1:71:6:71:13 | call to produce [element] | test.ps1:74:6:74:8 | x [element] | provenance | |
-| test.ps1:72:6:72:8 | x [element] | test.ps1:72:6:72:11 | ...[...] | provenance | |
-| test.ps1:73:6:73:8 | x [element] | test.ps1:73:6:73:11 | ...[...] | provenance | |
-| test.ps1:74:6:74:8 | x [element] | test.ps1:74:6:74:11 | ...[...] | provenance | |
-| test.ps1:76:9:79:2 | ${...} [element a] | test.ps1:81:6:81:11 | hash [element a] | provenance | |
-| test.ps1:76:9:79:2 | ${...} [element a] | test.ps1:85:6:85:11 | hash [element a] | provenance | |
-| test.ps1:77:7:77:18 | call to Source | test.ps1:76:9:79:2 | ${...} [element a] | provenance | |
-| test.ps1:81:6:81:11 | hash [element a] | test.ps1:81:6:81:16 | ...[...] | provenance | |
-| test.ps1:85:6:85:11 | hash [element a] | test.ps1:85:6:85:16 | ...[...] | provenance | |
-| test.ps1:86:1:86:6 | [post] hash [b] | test.ps1:87:6:87:11 | hash [b] | provenance | |
-| test.ps1:86:11:86:22 | call to Source | test.ps1:86:1:86:6 | [post] hash [b] | provenance | |
-| test.ps1:87:6:87:11 | hash [b] | test.ps1:87:6:87:13 | b | provenance | |
+| test.ps1:3:1:3:2 | [post] a [f] | test.ps1:4:6:4:7 | a [f] | provenance | |
+| test.ps1:3:8:3:17 | Call to Source | test.ps1:3:1:3:2 | [post] a [f] | provenance | |
+| test.ps1:4:6:4:7 | a [f] | test.ps1:4:6:4:9 | f | provenance | |
+| test.ps1:10:1:10:5 | [post] arr1 [element 3] | test.ps1:11:6:11:10 | arr1 [element 3] | provenance | |
+| test.ps1:10:12:10:21 | Call to Source | test.ps1:10:1:10:5 | [post] arr1 [element 3] | provenance | |
+| test.ps1:11:6:11:10 | arr1 [element 3] | test.ps1:11:6:11:13 | ...[...] | provenance | |
+| test.ps1:14:1:14:5 | [post] arr2 [element] | test.ps1:15:6:15:10 | arr2 [element] | provenance | |
+| test.ps1:14:19:14:28 | Call to Source | test.ps1:14:1:14:5 | [post] arr2 [element] | provenance | |
+| test.ps1:15:6:15:10 | arr2 [element] | test.ps1:15:6:15:13 | ...[...] | provenance | |
+| test.ps1:17:1:17:5 | [post] arr3 [element 3] | test.ps1:18:6:18:10 | arr3 [element 3] | provenance | |
+| test.ps1:17:12:17:21 | Call to Source | test.ps1:17:1:17:5 | [post] arr3 [element 3] | provenance | |
+| test.ps1:18:6:18:10 | arr3 [element 3] | test.ps1:18:6:18:20 | ...[...] | provenance | |
+| test.ps1:20:1:20:5 | [post] arr4 [element] | test.ps1:21:6:21:10 | arr4 [element] | provenance | |
+| test.ps1:20:20:20:29 | Call to Source | test.ps1:20:1:20:5 | [post] arr4 [element] | provenance | |
+| test.ps1:21:6:21:10 | arr4 [element] | test.ps1:21:6:21:21 | ...[...] | provenance | |
+| test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | test.ps1:24:6:24:10 | arr5 [element, element 1] | provenance | |
+| test.ps1:23:1:23:16 | [post] ...[...] [element 1] | test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | provenance | |
+| test.ps1:23:23:23:32 | Call to Source | test.ps1:23:1:23:16 | [post] ...[...] [element 1] | provenance | |
+| test.ps1:24:6:24:10 | arr5 [element, element 1] | test.ps1:24:6:24:21 | ...[...] [element 1] | provenance | |
+| test.ps1:24:6:24:21 | ...[...] [element 1] | test.ps1:24:6:24:24 | ...[...] | provenance | |
+| test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | test.ps1:28:6:28:10 | arr6 [element 1, element] | provenance | |
+| test.ps1:27:1:27:8 | [post] ...[...] [element] | test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | provenance | |
+| test.ps1:27:23:27:32 | Call to Source | test.ps1:27:1:27:8 | [post] ...[...] [element] | provenance | |
+| test.ps1:28:6:28:10 | arr6 [element 1, element] | test.ps1:28:6:28:13 | ...[...] [element] | provenance | |
+| test.ps1:28:6:28:13 | ...[...] [element] | test.ps1:28:6:28:24 | ...[...] | provenance | |
+| test.ps1:31:1:31:5 | [post] arr7 [element, element] | test.ps1:32:6:32:10 | arr7 [element, element] | provenance | |
+| test.ps1:31:1:31:5 | [post] arr7 [element, element] | test.ps1:33:6:33:10 | arr7 [element, element] | provenance | |
+| test.ps1:31:1:31:16 | [post] ...[...] [element] | test.ps1:31:1:31:5 | [post] arr7 [element, element] | provenance | |
+| test.ps1:31:31:31:40 | Call to Source | test.ps1:31:1:31:16 | [post] ...[...] [element] | provenance | |
+| test.ps1:32:6:32:10 | arr7 [element, element] | test.ps1:32:6:32:13 | ...[...] [element] | provenance | |
+| test.ps1:32:6:32:13 | ...[...] [element] | test.ps1:32:6:32:16 | ...[...] | provenance | |
+| test.ps1:33:6:33:10 | arr7 [element, element] | test.ps1:33:6:33:21 | ...[...] [element] | provenance | |
+| test.ps1:33:6:33:21 | ...[...] [element] | test.ps1:33:6:33:32 | ...[...] | provenance | |
+| test.ps1:35:6:35:16 | Call to Source | test.ps1:37:15:37:16 | x | provenance | |
+| test.ps1:37:9:37:16 | ...,... [element 2] | test.ps1:40:6:40:10 | arr8 [element 2] | provenance | |
+| test.ps1:37:9:37:16 | ...,... [element 2] | test.ps1:41:6:41:10 | arr8 [element 2] | provenance | |
+| test.ps1:37:15:37:16 | x | test.ps1:37:9:37:16 | ...,... [element 2] | provenance | |
+| test.ps1:40:6:40:10 | arr8 [element 2] | test.ps1:40:6:40:13 | ...[...] | provenance | |
+| test.ps1:41:6:41:10 | arr8 [element 2] | test.ps1:41:6:41:20 | ...[...] | provenance | |
+| test.ps1:43:6:43:16 | Call to Source | test.ps1:45:17:45:18 | y | provenance | |
+| test.ps1:45:11:45:18 | ...,... [element 2] | test.ps1:48:6:48:10 | arr9 [element 2] | provenance | |
+| test.ps1:45:11:45:18 | ...,... [element 2] | test.ps1:49:6:49:10 | arr9 [element 2] | provenance | |
+| test.ps1:45:17:45:18 | y | test.ps1:45:11:45:18 | ...,... [element 2] | provenance | |
+| test.ps1:48:6:48:10 | arr9 [element 2] | test.ps1:48:6:48:13 | ...[...] | provenance | |
+| test.ps1:49:6:49:10 | arr9 [element 2] | test.ps1:49:6:49:20 | ...[...] | provenance | |
+| test.ps1:88:1:88:5 | [post] hash [b] | test.ps1:89:6:89:10 | hash [b] | provenance | |
+| test.ps1:88:11:88:21 | Call to Source | test.ps1:88:1:88:5 | [post] hash [b] | provenance | |
+| test.ps1:89:6:89:10 | hash [b] | test.ps1:89:6:89:12 | b | provenance | |
nodes
-| test.ps1:1:1:1:3 | [post] a [f] | semmle.label | [post] a [f] |
-| test.ps1:1:8:1:18 | call to Source | semmle.label | call to Source |
-| test.ps1:2:6:2:8 | a [f] | semmle.label | a [f] |
-| test.ps1:2:6:2:10 | f | semmle.label | f |
-| test.ps1:8:1:8:6 | [post] arr1 [element 3] | semmle.label | [post] arr1 [element 3] |
-| test.ps1:8:1:8:6 | [post] arr1 [element 3] | semmle.label | [post] arr1 [element 3] |
-| test.ps1:8:12:8:22 | call to Source | semmle.label | call to Source |
-| test.ps1:9:6:9:11 | arr1 [element 3] | semmle.label | arr1 [element 3] |
-| test.ps1:9:6:9:11 | arr1 [element 3] | semmle.label | arr1 [element 3] |
-| test.ps1:9:6:9:14 | ...[...] | semmle.label | ...[...] |
-| test.ps1:12:1:12:6 | [post] arr2 [element] | semmle.label | [post] arr2 [element] |
-| test.ps1:12:19:12:29 | call to Source | semmle.label | call to Source |
-| test.ps1:13:6:13:11 | arr2 [element] | semmle.label | arr2 [element] |
-| test.ps1:13:6:13:14 | ...[...] | semmle.label | ...[...] |
-| test.ps1:15:1:15:6 | [post] arr3 [element 3] | semmle.label | [post] arr3 [element 3] |
-| test.ps1:15:1:15:6 | [post] arr3 [element 3] | semmle.label | [post] arr3 [element 3] |
-| test.ps1:15:12:15:22 | call to Source | semmle.label | call to Source |
-| test.ps1:16:6:16:11 | arr3 [element 3] | semmle.label | arr3 [element 3] |
-| test.ps1:16:6:16:11 | arr3 [element 3] | semmle.label | arr3 [element 3] |
-| test.ps1:16:6:16:21 | ...[...] | semmle.label | ...[...] |
-| test.ps1:18:1:18:6 | [post] arr4 [element] | semmle.label | [post] arr4 [element] |
-| test.ps1:18:20:18:30 | call to Source | semmle.label | call to Source |
-| test.ps1:19:6:19:11 | arr4 [element] | semmle.label | arr4 [element] |
-| test.ps1:19:6:19:22 | ...[...] | semmle.label | ...[...] |
-| test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | semmle.label | [post] arr5 [element, element 1] |
-| test.ps1:21:1:21:6 | [post] arr5 [element, element 1] | semmle.label | [post] arr5 [element, element 1] |
-| test.ps1:21:1:21:17 | [post] ...[...] [element 1] | semmle.label | [post] ...[...] [element 1] |
-| test.ps1:21:1:21:17 | [post] ...[...] [element 1] | semmle.label | [post] ...[...] [element 1] |
-| test.ps1:21:23:21:33 | call to Source | semmle.label | call to Source |
-| test.ps1:22:6:22:11 | arr5 [element, element 1] | semmle.label | arr5 [element, element 1] |
-| test.ps1:22:6:22:11 | arr5 [element, element 1] | semmle.label | arr5 [element, element 1] |
-| test.ps1:22:6:22:22 | ...[...] [element 1] | semmle.label | ...[...] [element 1] |
-| test.ps1:22:6:22:22 | ...[...] [element 1] | semmle.label | ...[...] [element 1] |
-| test.ps1:22:6:22:25 | ...[...] | semmle.label | ...[...] |
-| test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | semmle.label | [post] arr6 [element 1, element] |
-| test.ps1:25:1:25:6 | [post] arr6 [element 1, element] | semmle.label | [post] arr6 [element 1, element] |
-| test.ps1:25:1:25:9 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
-| test.ps1:25:23:25:33 | call to Source | semmle.label | call to Source |
-| test.ps1:26:6:26:11 | arr6 [element 1, element] | semmle.label | arr6 [element 1, element] |
-| test.ps1:26:6:26:11 | arr6 [element 1, element] | semmle.label | arr6 [element 1, element] |
-| test.ps1:26:6:26:14 | ...[...] [element] | semmle.label | ...[...] [element] |
-| test.ps1:26:6:26:25 | ...[...] | semmle.label | ...[...] |
-| test.ps1:29:1:29:6 | [post] arr7 [element, element] | semmle.label | [post] arr7 [element, element] |
-| test.ps1:29:1:29:17 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
-| test.ps1:29:31:29:41 | call to Source | semmle.label | call to Source |
-| test.ps1:30:6:30:11 | arr7 [element, element] | semmle.label | arr7 [element, element] |
-| test.ps1:30:6:30:14 | ...[...] [element] | semmle.label | ...[...] [element] |
-| test.ps1:30:6:30:17 | ...[...] | semmle.label | ...[...] |
-| test.ps1:31:6:31:11 | arr7 [element, element] | semmle.label | arr7 [element, element] |
-| test.ps1:31:6:31:22 | ...[...] [element] | semmle.label | ...[...] [element] |
-| test.ps1:31:6:31:33 | ...[...] | semmle.label | ...[...] |
-| test.ps1:33:6:33:17 | call to Source | semmle.label | call to Source |
-| test.ps1:35:9:35:17 | ...,... [element 2] | semmle.label | ...,... [element 2] |
-| test.ps1:35:15:35:17 | x | semmle.label | x |
-| test.ps1:38:6:38:11 | arr8 [element 2] | semmle.label | arr8 [element 2] |
-| test.ps1:38:6:38:14 | ...[...] | semmle.label | ...[...] |
-| test.ps1:39:6:39:11 | arr8 [element 2] | semmle.label | arr8 [element 2] |
-| test.ps1:39:6:39:21 | ...[...] | semmle.label | ...[...] |
-| test.ps1:41:6:41:17 | call to Source | semmle.label | call to Source |
-| test.ps1:43:11:43:19 | ...,... [element 2] | semmle.label | ...,... [element 2] |
-| test.ps1:43:17:43:19 | y | semmle.label | y |
-| test.ps1:46:6:46:11 | arr9 [element 2] | semmle.label | arr9 [element 2] |
-| test.ps1:46:6:46:14 | ...[...] | semmle.label | ...[...] |
-| test.ps1:47:6:47:11 | arr9 [element 2] | semmle.label | arr9 [element 2] |
-| test.ps1:47:6:47:21 | ...[...] | semmle.label | ...[...] |
-| test.ps1:52:22:54:6 | this [field] | semmle.label | this [field] |
-| test.ps1:53:14:53:19 | this [field] | semmle.label | this [field] |
-| test.ps1:53:14:53:25 | field | semmle.label | field |
-| test.ps1:59:1:59:9 | [post] myClass [field] | semmle.label | [post] myClass [field] |
-| test.ps1:59:18:59:29 | call to Source | semmle.label | call to Source |
-| test.ps1:61:1:61:9 | myClass [field] | semmle.label | myClass [field] |
-| test.ps1:64:10:64:21 | call to Source | semmle.label | call to Source |
-| test.ps1:65:10:65:21 | call to Source | semmle.label | call to Source |
-| test.ps1:66:10:66:21 | call to Source | semmle.label | call to Source |
-| test.ps1:67:5:67:7 | x | semmle.label | x |
-| test.ps1:68:5:68:7 | y | semmle.label | y |
-| test.ps1:68:5:68:11 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:68:5:68:11 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:68:9:68:11 | z | semmle.label | z |
-| test.ps1:71:6:71:13 | call to produce [element] | semmle.label | call to produce [element] |
-| test.ps1:72:6:72:8 | x [element] | semmle.label | x [element] |
-| test.ps1:72:6:72:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:73:6:73:8 | x [element] | semmle.label | x [element] |
-| test.ps1:73:6:73:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:74:6:74:8 | x [element] | semmle.label | x [element] |
-| test.ps1:74:6:74:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:76:9:79:2 | ${...} [element a] | semmle.label | ${...} [element a] |
-| test.ps1:77:7:77:18 | call to Source | semmle.label | call to Source |
-| test.ps1:81:6:81:11 | hash [element a] | semmle.label | hash [element a] |
-| test.ps1:81:6:81:16 | ...[...] | semmle.label | ...[...] |
-| test.ps1:85:6:85:11 | hash [element a] | semmle.label | hash [element a] |
-| test.ps1:85:6:85:16 | ...[...] | semmle.label | ...[...] |
-| test.ps1:86:1:86:6 | [post] hash [b] | semmle.label | [post] hash [b] |
-| test.ps1:86:11:86:22 | call to Source | semmle.label | call to Source |
-| test.ps1:87:6:87:11 | hash [b] | semmle.label | hash [b] |
-| test.ps1:87:6:87:13 | b | semmle.label | b |
+| test.ps1:3:1:3:2 | [post] a [f] | semmle.label | [post] a [f] |
+| test.ps1:3:8:3:17 | Call to Source | semmle.label | Call to Source |
+| test.ps1:4:6:4:7 | a [f] | semmle.label | a [f] |
+| test.ps1:4:6:4:9 | f | semmle.label | f |
+| test.ps1:10:1:10:5 | [post] arr1 [element 3] | semmle.label | [post] arr1 [element 3] |
+| test.ps1:10:12:10:21 | Call to Source | semmle.label | Call to Source |
+| test.ps1:11:6:11:10 | arr1 [element 3] | semmle.label | arr1 [element 3] |
+| test.ps1:11:6:11:13 | ...[...] | semmle.label | ...[...] |
+| test.ps1:14:1:14:5 | [post] arr2 [element] | semmle.label | [post] arr2 [element] |
+| test.ps1:14:19:14:28 | Call to Source | semmle.label | Call to Source |
+| test.ps1:15:6:15:10 | arr2 [element] | semmle.label | arr2 [element] |
+| test.ps1:15:6:15:13 | ...[...] | semmle.label | ...[...] |
+| test.ps1:17:1:17:5 | [post] arr3 [element 3] | semmle.label | [post] arr3 [element 3] |
+| test.ps1:17:12:17:21 | Call to Source | semmle.label | Call to Source |
+| test.ps1:18:6:18:10 | arr3 [element 3] | semmle.label | arr3 [element 3] |
+| test.ps1:18:6:18:20 | ...[...] | semmle.label | ...[...] |
+| test.ps1:20:1:20:5 | [post] arr4 [element] | semmle.label | [post] arr4 [element] |
+| test.ps1:20:20:20:29 | Call to Source | semmle.label | Call to Source |
+| test.ps1:21:6:21:10 | arr4 [element] | semmle.label | arr4 [element] |
+| test.ps1:21:6:21:21 | ...[...] | semmle.label | ...[...] |
+| test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | semmle.label | [post] arr5 [element, element 1] |
+| test.ps1:23:1:23:16 | [post] ...[...] [element 1] | semmle.label | [post] ...[...] [element 1] |
+| test.ps1:23:23:23:32 | Call to Source | semmle.label | Call to Source |
+| test.ps1:24:6:24:10 | arr5 [element, element 1] | semmle.label | arr5 [element, element 1] |
+| test.ps1:24:6:24:21 | ...[...] [element 1] | semmle.label | ...[...] [element 1] |
+| test.ps1:24:6:24:24 | ...[...] | semmle.label | ...[...] |
+| test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | semmle.label | [post] arr6 [element 1, element] |
+| test.ps1:27:1:27:8 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
+| test.ps1:27:23:27:32 | Call to Source | semmle.label | Call to Source |
+| test.ps1:28:6:28:10 | arr6 [element 1, element] | semmle.label | arr6 [element 1, element] |
+| test.ps1:28:6:28:13 | ...[...] [element] | semmle.label | ...[...] [element] |
+| test.ps1:28:6:28:24 | ...[...] | semmle.label | ...[...] |
+| test.ps1:31:1:31:5 | [post] arr7 [element, element] | semmle.label | [post] arr7 [element, element] |
+| test.ps1:31:1:31:16 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
+| test.ps1:31:31:31:40 | Call to Source | semmle.label | Call to Source |
+| test.ps1:32:6:32:10 | arr7 [element, element] | semmle.label | arr7 [element, element] |
+| test.ps1:32:6:32:13 | ...[...] [element] | semmle.label | ...[...] [element] |
+| test.ps1:32:6:32:16 | ...[...] | semmle.label | ...[...] |
+| test.ps1:33:6:33:10 | arr7 [element, element] | semmle.label | arr7 [element, element] |
+| test.ps1:33:6:33:21 | ...[...] [element] | semmle.label | ...[...] [element] |
+| test.ps1:33:6:33:32 | ...[...] | semmle.label | ...[...] |
+| test.ps1:35:6:35:16 | Call to Source | semmle.label | Call to Source |
+| test.ps1:37:9:37:16 | ...,... [element 2] | semmle.label | ...,... [element 2] |
+| test.ps1:37:15:37:16 | x | semmle.label | x |
+| test.ps1:40:6:40:10 | arr8 [element 2] | semmle.label | arr8 [element 2] |
+| test.ps1:40:6:40:13 | ...[...] | semmle.label | ...[...] |
+| test.ps1:41:6:41:10 | arr8 [element 2] | semmle.label | arr8 [element 2] |
+| test.ps1:41:6:41:20 | ...[...] | semmle.label | ...[...] |
+| test.ps1:43:6:43:16 | Call to Source | semmle.label | Call to Source |
+| test.ps1:45:11:45:18 | ...,... [element 2] | semmle.label | ...,... [element 2] |
+| test.ps1:45:17:45:18 | y | semmle.label | y |
+| test.ps1:48:6:48:10 | arr9 [element 2] | semmle.label | arr9 [element 2] |
+| test.ps1:48:6:48:13 | ...[...] | semmle.label | ...[...] |
+| test.ps1:49:6:49:10 | arr9 [element 2] | semmle.label | arr9 [element 2] |
+| test.ps1:49:6:49:20 | ...[...] | semmle.label | ...[...] |
+| test.ps1:88:1:88:5 | [post] hash [b] | semmle.label | [post] hash [b] |
+| test.ps1:88:11:88:21 | Call to Source | semmle.label | Call to Source |
+| test.ps1:89:6:89:10 | hash [b] | semmle.label | hash [b] |
+| test.ps1:89:6:89:12 | b | semmle.label | b |
subpaths
testFailures
+| test.ps1:55:26:55:44 | # $ hasValueFlow=12 | Missing result: hasValueFlow=12 |
+| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
+| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
+| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
+| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
+| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
+| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
+| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
+| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
+| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
+| test.ps1:83:17:83:35 | # $ hasValueFlow=16 | Missing result: hasValueFlow=16 |
+| test.ps1:87:17:87:45 | # $ SPURIOUS: hasValueFlow=16 | Fixed spurious result: hasValueFlow=16 |
#select
-| test.ps1:2:6:2:10 | f | test.ps1:1:8:1:18 | call to Source | test.ps1:2:6:2:10 | f | $@ | test.ps1:1:8:1:18 | call to Source | call to Source |
-| test.ps1:9:6:9:14 | ...[...] | test.ps1:8:12:8:22 | call to Source | test.ps1:9:6:9:14 | ...[...] | $@ | test.ps1:8:12:8:22 | call to Source | call to Source |
-| test.ps1:13:6:13:14 | ...[...] | test.ps1:12:19:12:29 | call to Source | test.ps1:13:6:13:14 | ...[...] | $@ | test.ps1:12:19:12:29 | call to Source | call to Source |
-| test.ps1:16:6:16:21 | ...[...] | test.ps1:15:12:15:22 | call to Source | test.ps1:16:6:16:21 | ...[...] | $@ | test.ps1:15:12:15:22 | call to Source | call to Source |
-| test.ps1:19:6:19:22 | ...[...] | test.ps1:18:20:18:30 | call to Source | test.ps1:19:6:19:22 | ...[...] | $@ | test.ps1:18:20:18:30 | call to Source | call to Source |
-| test.ps1:22:6:22:25 | ...[...] | test.ps1:21:23:21:33 | call to Source | test.ps1:22:6:22:25 | ...[...] | $@ | test.ps1:21:23:21:33 | call to Source | call to Source |
-| test.ps1:26:6:26:25 | ...[...] | test.ps1:25:23:25:33 | call to Source | test.ps1:26:6:26:25 | ...[...] | $@ | test.ps1:25:23:25:33 | call to Source | call to Source |
-| test.ps1:30:6:30:17 | ...[...] | test.ps1:29:31:29:41 | call to Source | test.ps1:30:6:30:17 | ...[...] | $@ | test.ps1:29:31:29:41 | call to Source | call to Source |
-| test.ps1:31:6:31:33 | ...[...] | test.ps1:29:31:29:41 | call to Source | test.ps1:31:6:31:33 | ...[...] | $@ | test.ps1:29:31:29:41 | call to Source | call to Source |
-| test.ps1:38:6:38:14 | ...[...] | test.ps1:33:6:33:17 | call to Source | test.ps1:38:6:38:14 | ...[...] | $@ | test.ps1:33:6:33:17 | call to Source | call to Source |
-| test.ps1:39:6:39:21 | ...[...] | test.ps1:33:6:33:17 | call to Source | test.ps1:39:6:39:21 | ...[...] | $@ | test.ps1:33:6:33:17 | call to Source | call to Source |
-| test.ps1:46:6:46:14 | ...[...] | test.ps1:41:6:41:17 | call to Source | test.ps1:46:6:46:14 | ...[...] | $@ | test.ps1:41:6:41:17 | call to Source | call to Source |
-| test.ps1:47:6:47:21 | ...[...] | test.ps1:41:6:41:17 | call to Source | test.ps1:47:6:47:21 | ...[...] | $@ | test.ps1:41:6:41:17 | call to Source | call to Source |
-| test.ps1:53:14:53:25 | field | test.ps1:59:18:59:29 | call to Source | test.ps1:53:14:53:25 | field | $@ | test.ps1:59:18:59:29 | call to Source | call to Source |
-| test.ps1:72:6:72:11 | ...[...] | test.ps1:64:10:64:21 | call to Source | test.ps1:72:6:72:11 | ...[...] | $@ | test.ps1:64:10:64:21 | call to Source | call to Source |
-| test.ps1:72:6:72:11 | ...[...] | test.ps1:65:10:65:21 | call to Source | test.ps1:72:6:72:11 | ...[...] | $@ | test.ps1:65:10:65:21 | call to Source | call to Source |
-| test.ps1:72:6:72:11 | ...[...] | test.ps1:66:10:66:21 | call to Source | test.ps1:72:6:72:11 | ...[...] | $@ | test.ps1:66:10:66:21 | call to Source | call to Source |
-| test.ps1:73:6:73:11 | ...[...] | test.ps1:64:10:64:21 | call to Source | test.ps1:73:6:73:11 | ...[...] | $@ | test.ps1:64:10:64:21 | call to Source | call to Source |
-| test.ps1:73:6:73:11 | ...[...] | test.ps1:65:10:65:21 | call to Source | test.ps1:73:6:73:11 | ...[...] | $@ | test.ps1:65:10:65:21 | call to Source | call to Source |
-| test.ps1:73:6:73:11 | ...[...] | test.ps1:66:10:66:21 | call to Source | test.ps1:73:6:73:11 | ...[...] | $@ | test.ps1:66:10:66:21 | call to Source | call to Source |
-| test.ps1:74:6:74:11 | ...[...] | test.ps1:64:10:64:21 | call to Source | test.ps1:74:6:74:11 | ...[...] | $@ | test.ps1:64:10:64:21 | call to Source | call to Source |
-| test.ps1:74:6:74:11 | ...[...] | test.ps1:65:10:65:21 | call to Source | test.ps1:74:6:74:11 | ...[...] | $@ | test.ps1:65:10:65:21 | call to Source | call to Source |
-| test.ps1:74:6:74:11 | ...[...] | test.ps1:66:10:66:21 | call to Source | test.ps1:74:6:74:11 | ...[...] | $@ | test.ps1:66:10:66:21 | call to Source | call to Source |
-| test.ps1:81:6:81:16 | ...[...] | test.ps1:77:7:77:18 | call to Source | test.ps1:81:6:81:16 | ...[...] | $@ | test.ps1:77:7:77:18 | call to Source | call to Source |
-| test.ps1:85:6:85:16 | ...[...] | test.ps1:77:7:77:18 | call to Source | test.ps1:85:6:85:16 | ...[...] | $@ | test.ps1:77:7:77:18 | call to Source | call to Source |
-| test.ps1:87:6:87:13 | b | test.ps1:86:11:86:22 | call to Source | test.ps1:87:6:87:13 | b | $@ | test.ps1:86:11:86:22 | call to Source | call to Source |
+| test.ps1:4:6:4:9 | f | test.ps1:3:8:3:17 | Call to Source | test.ps1:4:6:4:9 | f | $@ | test.ps1:3:8:3:17 | Call to Source | Call to Source |
+| test.ps1:11:6:11:13 | ...[...] | test.ps1:10:12:10:21 | Call to Source | test.ps1:11:6:11:13 | ...[...] | $@ | test.ps1:10:12:10:21 | Call to Source | Call to Source |
+| test.ps1:15:6:15:13 | ...[...] | test.ps1:14:19:14:28 | Call to Source | test.ps1:15:6:15:13 | ...[...] | $@ | test.ps1:14:19:14:28 | Call to Source | Call to Source |
+| test.ps1:18:6:18:20 | ...[...] | test.ps1:17:12:17:21 | Call to Source | test.ps1:18:6:18:20 | ...[...] | $@ | test.ps1:17:12:17:21 | Call to Source | Call to Source |
+| test.ps1:21:6:21:21 | ...[...] | test.ps1:20:20:20:29 | Call to Source | test.ps1:21:6:21:21 | ...[...] | $@ | test.ps1:20:20:20:29 | Call to Source | Call to Source |
+| test.ps1:24:6:24:24 | ...[...] | test.ps1:23:23:23:32 | Call to Source | test.ps1:24:6:24:24 | ...[...] | $@ | test.ps1:23:23:23:32 | Call to Source | Call to Source |
+| test.ps1:28:6:28:24 | ...[...] | test.ps1:27:23:27:32 | Call to Source | test.ps1:28:6:28:24 | ...[...] | $@ | test.ps1:27:23:27:32 | Call to Source | Call to Source |
+| test.ps1:32:6:32:16 | ...[...] | test.ps1:31:31:31:40 | Call to Source | test.ps1:32:6:32:16 | ...[...] | $@ | test.ps1:31:31:31:40 | Call to Source | Call to Source |
+| test.ps1:33:6:33:32 | ...[...] | test.ps1:31:31:31:40 | Call to Source | test.ps1:33:6:33:32 | ...[...] | $@ | test.ps1:31:31:31:40 | Call to Source | Call to Source |
+| test.ps1:40:6:40:13 | ...[...] | test.ps1:35:6:35:16 | Call to Source | test.ps1:40:6:40:13 | ...[...] | $@ | test.ps1:35:6:35:16 | Call to Source | Call to Source |
+| test.ps1:41:6:41:20 | ...[...] | test.ps1:35:6:35:16 | Call to Source | test.ps1:41:6:41:20 | ...[...] | $@ | test.ps1:35:6:35:16 | Call to Source | Call to Source |
+| test.ps1:48:6:48:13 | ...[...] | test.ps1:43:6:43:16 | Call to Source | test.ps1:48:6:48:13 | ...[...] | $@ | test.ps1:43:6:43:16 | Call to Source | Call to Source |
+| test.ps1:49:6:49:20 | ...[...] | test.ps1:43:6:43:16 | Call to Source | test.ps1:49:6:49:20 | ...[...] | $@ | test.ps1:43:6:43:16 | Call to Source | Call to Source |
+| test.ps1:89:6:89:12 | b | test.ps1:88:11:88:21 | Call to Source | test.ps1:89:6:89:12 | b | $@ | test.ps1:88:11:88:21 | Call to Source | Call to Source |
diff --git a/powershell/ql/test/library-tests/dataflow/fields/test.ps1 b/powershell/ql/test/library-tests/dataflow/fields/test.ps1
index a73c4fb79f38..fcd375c0516b 100644
--- a/powershell/ql/test/library-tests/dataflow/fields/test.ps1
+++ b/powershell/ql/test/library-tests/dataflow/fields/test.ps1
@@ -1,3 +1,5 @@
+param($a, $arr1, $arr2, $arr3, $arr4, $arr5, $arr6, $arr7, $arr8, $arr9, $unknown, $unknown1, $unknown2, $unknown3, $unknown4, $unknown5, $unknown6, $unknown7, $unknown8)
+
$a.f = Source "1"
Sink $a.f # $ hasValueFlow=1
diff --git a/powershell/ql/test/library-tests/dataflow/local/flow.expected b/powershell/ql/test/library-tests/dataflow/local/flow.expected
index 96670d797bb4..080873884dfe 100644
--- a/powershell/ql/test/library-tests/dataflow/local/flow.expected
+++ b/powershell/ql/test/library-tests/dataflow/local/flow.expected
@@ -1,56 +1,51 @@
-| test.ps1:1:1:1:4 | a1 | test.ps1:2:6:2:9 | a1 |
-| test.ps1:1:7:1:13 | call to Source | test.ps1:1:1:1:4 | a1 |
-| test.ps1:1:7:1:13 | call to Source | test.ps1:1:1:1:13 | ...=... |
-| test.ps1:2:1:2:9 | call to Sink | test.ps1:2:1:2:9 | pre-return value for call to Sink |
-| test.ps1:2:1:2:9 | call to Sink | test.ps1:2:1:2:9 | pre-return value for call to Sink |
-| test.ps1:2:1:2:9 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:2:1:2:9 | pre-return value for call to Sink | test.ps1:2:1:2:9 | implicit unwrapping of call to Sink |
-| test.ps1:4:1:4:3 | b | test.ps1:5:4:5:6 | b |
-| test.ps1:4:6:4:13 | call to GetBool | test.ps1:4:1:4:3 | b |
-| test.ps1:4:6:4:13 | call to GetBool | test.ps1:4:1:4:13 | ...=... |
-| test.ps1:5:4:5:6 | b | test.ps1:10:14:10:16 | b |
-| test.ps1:6:5:6:8 | a2 | test.ps1:8:6:8:9 | a2 |
-| test.ps1:6:11:6:17 | call to Source | test.ps1:6:5:6:8 | a2 |
-| test.ps1:6:11:6:17 | call to Source | test.ps1:6:5:6:17 | ...=... |
-| test.ps1:8:1:8:9 | call to Sink | test.ps1:8:1:8:9 | pre-return value for call to Sink |
-| test.ps1:8:1:8:9 | call to Sink | test.ps1:8:1:8:9 | pre-return value for call to Sink |
-| test.ps1:8:1:8:9 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:8:1:8:9 | pre-return value for call to Sink | test.ps1:8:1:8:9 | implicit unwrapping of call to Sink |
-| test.ps1:10:1:10:3 | c | test.ps1:11:6:11:8 | c |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:1:10:3 | c |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:1:10:16 | ...=... |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:6:10:16 | [...]... |
-| test.ps1:10:14:10:16 | b | test.ps1:10:6:10:16 | [...]... |
-| test.ps1:11:1:11:8 | call to Sink | test.ps1:11:1:11:8 | pre-return value for call to Sink |
-| test.ps1:11:1:11:8 | call to Sink | test.ps1:11:1:11:8 | pre-return value for call to Sink |
-| test.ps1:11:1:11:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:11:1:11:8 | pre-return value for call to Sink | test.ps1:11:1:11:8 | implicit unwrapping of call to Sink |
-| test.ps1:11:6:11:8 | [post] c | test.ps1:13:7:13:9 | c |
-| test.ps1:11:6:11:8 | c | test.ps1:13:7:13:9 | c |
-| test.ps1:13:1:13:3 | d | test.ps1:14:6:14:8 | d |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:1:13:3 | d |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:1:13:10 | ...=... |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:6:13:10 | (...) |
-| test.ps1:13:7:13:9 | c | test.ps1:13:6:13:10 | (...) |
-| test.ps1:13:7:13:9 | c | test.ps1:13:7:13:9 | c |
-| test.ps1:14:1:14:8 | call to Sink | test.ps1:14:1:14:8 | pre-return value for call to Sink |
-| test.ps1:14:1:14:8 | call to Sink | test.ps1:14:1:14:8 | pre-return value for call to Sink |
-| test.ps1:14:1:14:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:14:1:14:8 | pre-return value for call to Sink | test.ps1:14:1:14:8 | implicit unwrapping of call to Sink |
-| test.ps1:14:6:14:8 | [post] d | test.ps1:16:6:16:8 | d |
-| test.ps1:14:6:14:8 | d | test.ps1:16:6:16:8 | d |
-| test.ps1:16:1:16:3 | e | test.ps1:17:6:17:8 | e |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:1:16:3 | e |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:1:16:12 | ...=... |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:6:16:12 | ...+... |
-| test.ps1:17:1:17:8 | call to Sink | test.ps1:17:1:17:8 | pre-return value for call to Sink |
-| test.ps1:17:1:17:8 | call to Sink | test.ps1:17:1:17:8 | pre-return value for call to Sink |
-| test.ps1:17:1:17:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:17:1:17:8 | pre-return value for call to Sink | test.ps1:17:1:17:8 | implicit unwrapping of call to Sink |
-| test.ps1:19:1:19:3 | f | test.ps1:21:25:21:27 | f |
-| test.ps1:19:6:19:12 | call to Source | test.ps1:19:1:19:3 | f |
-| test.ps1:19:6:19:12 | call to Source | test.ps1:19:1:19:12 | ...=... |
-| test.ps1:21:1:21:28 | call to Sink | test.ps1:21:1:21:28 | pre-return value for call to Sink |
-| test.ps1:21:1:21:28 | call to Sink | test.ps1:21:1:21:28 | pre-return value for call to Sink |
-| test.ps1:21:1:21:28 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:21:1:21:28 | pre-return value for call to Sink | test.ps1:21:1:21:28 | implicit unwrapping of call to Sink |
+| test.ps1:1:1:1:3 | a1 | test.ps1:2:6:2:8 | a1 |
+| test.ps1:1:7:1:12 | Call to Source | test.ps1:1:1:1:3 | a1 |
+| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
+| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
+| test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
+| test.ps1:4:1:4:2 | b | test.ps1:5:4:5:5 | b |
+| test.ps1:4:6:4:12 | Call to GetBool | test.ps1:4:1:4:2 | b |
+| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
+| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
+| test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
+| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
+| test.ps1:5:4:5:5 | b | test.ps1:10:14:10:15 | b |
+| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi |
+| test.ps1:6:11:6:16 | Call to Source | test.ps1:6:5:6:7 | a2 |
+| test.ps1:6:11:6:16 | [input] phi | test.ps1:5:1:7:1 | phi |
+| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
+| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
+| test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
+| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |
+| test.ps1:10:6:10:15 | [...]... | test.ps1:10:1:10:2 | c |
+| test.ps1:10:14:10:15 | b | test.ps1:10:6:10:15 | [...]... |
+| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
+| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
+| test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
+| test.ps1:11:6:11:7 | [post] c | test.ps1:13:7:13:8 | c |
+| test.ps1:11:6:11:7 | c | test.ps1:13:7:13:8 | c |
+| test.ps1:13:1:13:2 | d | test.ps1:14:6:14:7 | d |
+| test.ps1:13:6:13:9 | (...) | test.ps1:13:1:13:2 | d |
+| test.ps1:13:7:13:8 | c | test.ps1:13:6:13:9 | (...) |
+| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
+| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
+| test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
+| test.ps1:14:6:14:7 | [post] d | test.ps1:16:6:16:7 | d |
+| test.ps1:14:6:14:7 | d | test.ps1:16:6:16:7 | d |
+| test.ps1:16:1:16:2 | e | test.ps1:17:6:17:7 | e |
+| test.ps1:16:6:16:11 | ...+... | test.ps1:16:1:16:2 | e |
+| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
+| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
+| test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
+| test.ps1:19:1:19:2 | f | test.ps1:21:25:21:26 | f |
+| test.ps1:19:6:19:11 | Call to Source | test.ps1:19:1:19:2 | f |
+| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
+| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
+| test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
diff --git a/powershell/ql/test/library-tests/dataflow/local/taint.expected b/powershell/ql/test/library-tests/dataflow/local/taint.expected
index 923c723a31f8..5a68287270e1 100644
--- a/powershell/ql/test/library-tests/dataflow/local/taint.expected
+++ b/powershell/ql/test/library-tests/dataflow/local/taint.expected
@@ -1,65 +1,61 @@
-| test.ps1:1:1:1:4 | a1 | test.ps1:2:6:2:9 | a1 |
-| test.ps1:1:7:1:13 | call to Source | test.ps1:1:1:1:4 | a1 |
-| test.ps1:1:7:1:13 | call to Source | test.ps1:1:1:1:13 | ...=... |
-| test.ps1:2:1:2:9 | call to Sink | test.ps1:2:1:2:9 | pre-return value for call to Sink |
-| test.ps1:2:1:2:9 | call to Sink | test.ps1:2:1:2:9 | pre-return value for call to Sink |
-| test.ps1:2:1:2:9 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:2:1:2:9 | pre-return value for call to Sink | test.ps1:2:1:2:9 | implicit unwrapping of call to Sink |
-| test.ps1:2:1:2:9 | pre-return value for call to Sink | test.ps1:2:1:2:9 | implicit unwrapping of call to Sink |
-| test.ps1:4:1:4:3 | b | test.ps1:5:4:5:6 | b |
-| test.ps1:4:6:4:13 | call to GetBool | test.ps1:4:1:4:3 | b |
-| test.ps1:4:6:4:13 | call to GetBool | test.ps1:4:1:4:13 | ...=... |
-| test.ps1:5:4:5:6 | b | test.ps1:10:14:10:16 | b |
-| test.ps1:6:5:6:8 | a2 | test.ps1:8:6:8:9 | a2 |
-| test.ps1:6:11:6:17 | call to Source | test.ps1:6:5:6:8 | a2 |
-| test.ps1:6:11:6:17 | call to Source | test.ps1:6:5:6:17 | ...=... |
-| test.ps1:8:1:8:9 | call to Sink | test.ps1:8:1:8:9 | pre-return value for call to Sink |
-| test.ps1:8:1:8:9 | call to Sink | test.ps1:8:1:8:9 | pre-return value for call to Sink |
-| test.ps1:8:1:8:9 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:8:1:8:9 | pre-return value for call to Sink | test.ps1:8:1:8:9 | implicit unwrapping of call to Sink |
-| test.ps1:8:1:8:9 | pre-return value for call to Sink | test.ps1:8:1:8:9 | implicit unwrapping of call to Sink |
-| test.ps1:10:1:10:3 | c | test.ps1:11:6:11:8 | c |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:1:10:3 | c |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:1:10:16 | ...=... |
-| test.ps1:10:6:10:16 | [...]... | test.ps1:10:6:10:16 | [...]... |
-| test.ps1:10:14:10:16 | b | test.ps1:10:6:10:16 | [...]... |
-| test.ps1:11:1:11:8 | call to Sink | test.ps1:11:1:11:8 | pre-return value for call to Sink |
-| test.ps1:11:1:11:8 | call to Sink | test.ps1:11:1:11:8 | pre-return value for call to Sink |
-| test.ps1:11:1:11:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:11:1:11:8 | pre-return value for call to Sink | test.ps1:11:1:11:8 | implicit unwrapping of call to Sink |
-| test.ps1:11:1:11:8 | pre-return value for call to Sink | test.ps1:11:1:11:8 | implicit unwrapping of call to Sink |
-| test.ps1:11:6:11:8 | [post] c | test.ps1:13:7:13:9 | c |
-| test.ps1:11:6:11:8 | c | test.ps1:13:7:13:9 | c |
-| test.ps1:13:1:13:3 | d | test.ps1:14:6:14:8 | d |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:1:13:3 | d |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:1:13:10 | ...=... |
-| test.ps1:13:6:13:10 | (...) | test.ps1:13:6:13:10 | (...) |
-| test.ps1:13:7:13:9 | c | test.ps1:13:6:13:10 | (...) |
-| test.ps1:13:7:13:9 | c | test.ps1:13:7:13:9 | c |
-| test.ps1:14:1:14:8 | call to Sink | test.ps1:14:1:14:8 | pre-return value for call to Sink |
-| test.ps1:14:1:14:8 | call to Sink | test.ps1:14:1:14:8 | pre-return value for call to Sink |
-| test.ps1:14:1:14:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:14:1:14:8 | pre-return value for call to Sink | test.ps1:14:1:14:8 | implicit unwrapping of call to Sink |
-| test.ps1:14:1:14:8 | pre-return value for call to Sink | test.ps1:14:1:14:8 | implicit unwrapping of call to Sink |
-| test.ps1:14:6:14:8 | [post] d | test.ps1:16:6:16:8 | d |
-| test.ps1:14:6:14:8 | d | test.ps1:16:6:16:8 | d |
-| test.ps1:16:1:16:3 | e | test.ps1:17:6:17:8 | e |
-| test.ps1:16:6:16:8 | d | test.ps1:16:6:16:12 | ...+... |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:1:16:3 | e |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:1:16:12 | ...=... |
-| test.ps1:16:6:16:12 | ...+... | test.ps1:16:6:16:12 | ...+... |
-| test.ps1:16:11:16:12 | 1 | test.ps1:16:6:16:12 | ...+... |
-| test.ps1:17:1:17:8 | call to Sink | test.ps1:17:1:17:8 | pre-return value for call to Sink |
-| test.ps1:17:1:17:8 | call to Sink | test.ps1:17:1:17:8 | pre-return value for call to Sink |
-| test.ps1:17:1:17:8 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:17:1:17:8 | pre-return value for call to Sink | test.ps1:17:1:17:8 | implicit unwrapping of call to Sink |
-| test.ps1:17:1:17:8 | pre-return value for call to Sink | test.ps1:17:1:17:8 | implicit unwrapping of call to Sink |
-| test.ps1:19:1:19:3 | f | test.ps1:21:25:21:27 | f |
-| test.ps1:19:6:19:12 | call to Source | test.ps1:19:1:19:3 | f |
-| test.ps1:19:6:19:12 | call to Source | test.ps1:19:1:19:12 | ...=... |
-| test.ps1:21:1:21:28 | call to Sink | test.ps1:21:1:21:28 | pre-return value for call to Sink |
-| test.ps1:21:1:21:28 | call to Sink | test.ps1:21:1:21:28 | pre-return value for call to Sink |
-| test.ps1:21:1:21:28 | implicit unwrapping of call to Sink | test.ps1:1:1:21:28 | return value for test.ps1 |
-| test.ps1:21:1:21:28 | pre-return value for call to Sink | test.ps1:21:1:21:28 | implicit unwrapping of call to Sink |
-| test.ps1:21:1:21:28 | pre-return value for call to Sink | test.ps1:21:1:21:28 | implicit unwrapping of call to Sink |
-| test.ps1:21:25:21:27 | f | test.ps1:21:6:21:28 | here is a string: $f |
+| test.ps1:1:1:1:3 | a1 | test.ps1:2:6:2:8 | a1 |
+| test.ps1:1:7:1:12 | Call to Source | test.ps1:1:1:1:3 | a1 |
+| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
+| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
+| test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
+| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
+| test.ps1:4:1:4:2 | b | test.ps1:5:4:5:5 | b |
+| test.ps1:4:6:4:12 | Call to GetBool | test.ps1:4:1:4:2 | b |
+| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
+| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
+| test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
+| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
+| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
+| test.ps1:5:4:5:5 | b | test.ps1:10:14:10:15 | b |
+| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi |
+| test.ps1:6:11:6:16 | Call to Source | test.ps1:6:5:6:7 | a2 |
+| test.ps1:6:11:6:16 | [input] phi | test.ps1:5:1:7:1 | phi |
+| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
+| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
+| test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
+| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
+| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |
+| test.ps1:10:6:10:15 | [...]... | test.ps1:10:1:10:2 | c |
+| test.ps1:10:14:10:15 | b | test.ps1:10:6:10:15 | [...]... |
+| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
+| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
+| test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
+| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
+| test.ps1:11:6:11:7 | [post] c | test.ps1:13:7:13:8 | c |
+| test.ps1:11:6:11:7 | c | test.ps1:13:7:13:8 | c |
+| test.ps1:13:1:13:2 | d | test.ps1:14:6:14:7 | d |
+| test.ps1:13:6:13:9 | (...) | test.ps1:13:1:13:2 | d |
+| test.ps1:13:7:13:8 | c | test.ps1:13:6:13:9 | (...) |
+| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
+| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
+| test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
+| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
+| test.ps1:14:6:14:7 | [post] d | test.ps1:16:6:16:7 | d |
+| test.ps1:14:6:14:7 | d | test.ps1:16:6:16:7 | d |
+| test.ps1:16:1:16:2 | e | test.ps1:17:6:17:7 | e |
+| test.ps1:16:6:16:7 | d | test.ps1:16:6:16:11 | ...+... |
+| test.ps1:16:6:16:11 | ...+... | test.ps1:16:1:16:2 | e |
+| test.ps1:16:11:16:11 | 1 | test.ps1:16:6:16:11 | ...+... |
+| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
+| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
+| test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
+| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
+| test.ps1:19:1:19:2 | f | test.ps1:21:25:21:26 | f |
+| test.ps1:19:6:19:11 | Call to Source | test.ps1:19:1:19:2 | f |
+| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
+| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
+| test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
+| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
+| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
+| test.ps1:21:25:21:26 | f | test.ps1:21:6:21:27 | here is a string: $f |
diff --git a/powershell/ql/test/library-tests/dataflow/params/test.expected b/powershell/ql/test/library-tests/dataflow/params/test.expected
index 2387ed8cbcf0..d9110ac4f4a6 100644
--- a/powershell/ql/test/library-tests/dataflow/params/test.expected
+++ b/powershell/ql/test/library-tests/dataflow/params/test.expected
@@ -1,243 +1,243 @@
models
edges
-| global.ps1:1:7:1:23 | Source1 | global.ps1:3:6:3:14 | Source1 | provenance | |
-| global.ps1:1:25:1:41 | Source2 | global.ps1:4:6:4:14 | Source2 | provenance | |
-| global.ps1:1:43:1:59 | Source3 | global.ps1:5:6:5:14 | Source3 | provenance | |
-| global.ps1:1:61:1:77 | Source4 | global.ps1:6:6:6:14 | Source4 | provenance | |
-| test.ps1:1:14:1:16 | a | test.ps1:2:10:2:12 | a | provenance | |
-| test.ps1:5:6:5:16 | call to Source | test.ps1:6:5:6:7 | x | provenance | |
-| test.ps1:6:5:6:7 | x | test.ps1:1:14:1:16 | a | provenance | |
-| test.ps1:8:20:8:22 | x | test.ps1:9:10:9:12 | x | provenance | |
-| test.ps1:8:24:8:26 | y | test.ps1:10:10:10:12 | y | provenance | |
-| test.ps1:8:28:8:30 | z | test.ps1:11:10:11:12 | z | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:18:11:18:17 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:19:22:19:28 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:20:14:20:20 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:21:11:21:17 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:22:22:22:28 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:23:22:23:28 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:24:14:24:20 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:25:11:25:17 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:26:22:26:28 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:27:22:27:28 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:28:14:28:20 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:29:11:29:17 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:30:32:30:38 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:31:32:31:38 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:32:14:32:20 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:33:11:33:17 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:34:32:34:38 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:35:32:35:38 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:36:32:36:38 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:37:24:37:30 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:38:21:38:27 | first | provenance | |
-| test.ps1:14:10:14:20 | call to Source | test.ps1:39:32:39:38 | first | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:18:18:18:25 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:19:11:19:18 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:20:21:20:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:21:21:21:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:22:14:22:21 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:23:11:23:18 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:24:21:24:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:25:21:25:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:26:14:26:21 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:27:11:27:18 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:28:31:28:38 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:29:21:29:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:30:14:30:21 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:31:11:31:18 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:32:31:32:38 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:33:31:33:38 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:34:14:34:21 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:35:24:35:31 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:36:21:36:28 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:37:31:37:38 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:38:31:38:38 | second | provenance | |
-| test.ps1:15:11:15:21 | call to Source | test.ps1:39:24:39:31 | second | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:18:26:18:32 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:19:29:19:35 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:20:29:20:35 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:21:29:21:35 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:22:29:22:35 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:23:32:23:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:24:32:24:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:25:32:25:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:26:32:26:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:27:32:27:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:28:24:28:30 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:29:32:29:38 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:30:25:30:31 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:31:22:31:28 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:32:24:32:30 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:33:21:33:27 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:34:25:34:31 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:35:14:35:20 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:36:14:36:20 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:37:14:37:20 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:38:14:38:20 | third | provenance | |
-| test.ps1:16:10:16:20 | call to Source | test.ps1:39:14:39:20 | third | provenance | |
-| test.ps1:18:11:18:17 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:18:18:18:25 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:18:26:18:32 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:19:11:19:18 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:19:22:19:28 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:19:29:19:35 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:20:14:20:20 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:20:21:20:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:20:29:20:35 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:21:11:21:17 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:21:21:21:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:21:29:21:35 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:22:14:22:21 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:22:22:22:28 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:22:29:22:35 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:23:11:23:18 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:23:22:23:28 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:23:32:23:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:24:14:24:20 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:24:21:24:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:24:32:24:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:25:11:25:17 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:25:21:25:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:25:32:25:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:26:14:26:21 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:26:22:26:28 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:26:32:26:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:27:11:27:18 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:27:22:27:28 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:27:32:27:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:28:14:28:20 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:28:24:28:30 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:28:31:28:38 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:29:11:29:17 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:29:21:29:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:29:32:29:38 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:30:14:30:21 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:30:25:30:31 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:30:32:30:38 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:31:11:31:18 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:31:22:31:28 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:31:32:31:38 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:32:14:32:20 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:32:24:32:30 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:32:31:32:38 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:33:11:33:17 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:33:21:33:27 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:33:31:33:38 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:34:14:34:21 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:34:25:34:31 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:34:32:34:38 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:35:14:35:20 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:35:24:35:31 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:35:32:35:38 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:36:14:36:20 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:36:21:36:28 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:36:32:36:38 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:37:14:37:20 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:37:24:37:30 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:37:31:37:38 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:38:14:38:20 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:38:21:38:27 | first | test.ps1:8:20:8:22 | x | provenance | |
-| test.ps1:38:31:38:38 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:39:14:39:20 | third | test.ps1:8:28:8:30 | z | provenance | |
-| test.ps1:39:24:39:31 | second | test.ps1:8:24:8:26 | y | provenance | |
-| test.ps1:39:32:39:38 | first | test.ps1:8:20:8:22 | x | provenance | |
+| global.ps1:1:1:6:32 | Source1 | global.ps1:3:6:3:13 | Source1 | provenance | |
+| global.ps1:1:1:6:32 | Source2 | global.ps1:4:6:4:13 | Source2 | provenance | |
+| global.ps1:1:1:6:32 | Source3 | global.ps1:5:6:5:13 | Source3 | provenance | |
+| global.ps1:1:1:6:32 | Source4 | global.ps1:6:6:6:13 | Source4 | provenance | |
+| test.ps1:1:18:3:1 | a | test.ps1:2:10:2:11 | a | provenance | |
+| test.ps1:5:6:5:15 | Call to Source | test.ps1:6:5:6:6 | x | provenance | |
+| test.ps1:6:5:6:6 | x | test.ps1:1:18:3:1 | a | provenance | |
+| test.ps1:8:32:12:1 | x | test.ps1:9:10:9:11 | x | provenance | |
+| test.ps1:8:32:12:1 | y | test.ps1:10:10:10:11 | y | provenance | |
+| test.ps1:8:32:12:1 | z | test.ps1:11:10:11:11 | z | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:18:11:18:16 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:19:22:19:27 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:20:14:20:19 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:21:11:21:16 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:22:22:22:27 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:23:22:23:27 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:24:14:24:19 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:25:11:25:16 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:26:22:26:27 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:27:22:27:27 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:28:14:28:19 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:29:11:29:16 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:30:32:30:37 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:31:32:31:37 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:32:14:32:19 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:33:11:33:16 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:34:32:34:37 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:35:32:35:37 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:36:32:36:37 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:37:24:37:29 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:38:21:38:26 | first | provenance | |
+| test.ps1:14:10:14:19 | Call to Source | test.ps1:39:32:39:37 | first | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:18:18:18:24 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:19:11:19:17 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:20:21:20:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:21:21:21:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:22:14:22:20 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:23:11:23:17 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:24:21:24:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:25:21:25:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:26:14:26:20 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:27:11:27:17 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:28:31:28:37 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:29:21:29:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:30:14:30:20 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:31:11:31:17 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:32:31:32:37 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:33:31:33:37 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:34:14:34:20 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:35:24:35:30 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:36:21:36:27 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:37:31:37:37 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:38:31:38:37 | second | provenance | |
+| test.ps1:15:11:15:20 | Call to Source | test.ps1:39:24:39:30 | second | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:18:26:18:31 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:19:29:19:34 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:20:29:20:34 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:21:29:21:34 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:22:29:22:34 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:23:32:23:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:24:32:24:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:25:32:25:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:26:32:26:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:27:32:27:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:28:24:28:29 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:29:32:29:37 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:30:25:30:30 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:31:22:31:27 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:32:24:32:29 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:33:21:33:26 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:34:25:34:30 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:35:14:35:19 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:36:14:36:19 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:37:14:37:19 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:38:14:38:19 | third | provenance | |
+| test.ps1:16:10:16:19 | Call to Source | test.ps1:39:14:39:19 | third | provenance | |
+| test.ps1:18:11:18:16 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:18:18:18:24 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:18:26:18:31 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:19:11:19:17 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:19:22:19:27 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:19:29:19:34 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:20:14:20:19 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:20:21:20:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:20:29:20:34 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:21:11:21:16 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:21:21:21:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:21:29:21:34 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:22:14:22:20 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:22:22:22:27 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:22:29:22:34 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:23:11:23:17 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:23:22:23:27 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:23:32:23:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:24:14:24:19 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:24:21:24:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:24:32:24:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:25:11:25:16 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:25:21:25:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:25:32:25:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:26:14:26:20 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:26:22:26:27 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:26:32:26:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:27:11:27:17 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:27:22:27:27 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:27:32:27:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:28:14:28:19 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:28:24:28:29 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:28:31:28:37 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:29:11:29:16 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:29:21:29:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:29:32:29:37 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:30:14:30:20 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:30:25:30:30 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:30:32:30:37 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:31:11:31:17 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:31:22:31:27 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:31:32:31:37 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:32:14:32:19 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:32:24:32:29 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:32:31:32:37 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:33:11:33:16 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:33:21:33:26 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:33:31:33:37 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:34:14:34:20 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:34:25:34:30 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:34:32:34:37 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:35:14:35:19 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:35:24:35:30 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:35:32:35:37 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:36:14:36:19 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:36:21:36:27 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:36:32:36:37 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:37:14:37:19 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:37:24:37:29 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:37:31:37:37 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:38:14:38:19 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:38:21:38:26 | first | test.ps1:8:32:12:1 | x | provenance | |
+| test.ps1:38:31:38:37 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:39:14:39:19 | third | test.ps1:8:32:12:1 | z | provenance | |
+| test.ps1:39:24:39:30 | second | test.ps1:8:32:12:1 | y | provenance | |
+| test.ps1:39:32:39:37 | first | test.ps1:8:32:12:1 | x | provenance | |
nodes
-| global.ps1:1:7:1:23 | Source1 | semmle.label | Source1 |
-| global.ps1:1:25:1:41 | Source2 | semmle.label | Source2 |
-| global.ps1:1:43:1:59 | Source3 | semmle.label | Source3 |
-| global.ps1:1:61:1:77 | Source4 | semmle.label | Source4 |
-| global.ps1:3:6:3:14 | Source1 | semmle.label | Source1 |
-| global.ps1:4:6:4:14 | Source2 | semmle.label | Source2 |
-| global.ps1:5:6:5:14 | Source3 | semmle.label | Source3 |
-| global.ps1:6:6:6:14 | Source4 | semmle.label | Source4 |
-| test.ps1:1:14:1:16 | a | semmle.label | a |
-| test.ps1:2:10:2:12 | a | semmle.label | a |
-| test.ps1:5:6:5:16 | call to Source | semmle.label | call to Source |
-| test.ps1:6:5:6:7 | x | semmle.label | x |
-| test.ps1:8:20:8:22 | x | semmle.label | x |
-| test.ps1:8:24:8:26 | y | semmle.label | y |
-| test.ps1:8:28:8:30 | z | semmle.label | z |
-| test.ps1:9:10:9:12 | x | semmle.label | x |
-| test.ps1:10:10:10:12 | y | semmle.label | y |
-| test.ps1:11:10:11:12 | z | semmle.label | z |
-| test.ps1:14:10:14:20 | call to Source | semmle.label | call to Source |
-| test.ps1:15:11:15:21 | call to Source | semmle.label | call to Source |
-| test.ps1:16:10:16:20 | call to Source | semmle.label | call to Source |
-| test.ps1:18:11:18:17 | first | semmle.label | first |
-| test.ps1:18:18:18:25 | second | semmle.label | second |
-| test.ps1:18:26:18:32 | third | semmle.label | third |
-| test.ps1:19:11:19:18 | second | semmle.label | second |
-| test.ps1:19:22:19:28 | first | semmle.label | first |
-| test.ps1:19:29:19:35 | third | semmle.label | third |
-| test.ps1:20:14:20:20 | first | semmle.label | first |
-| test.ps1:20:21:20:28 | second | semmle.label | second |
-| test.ps1:20:29:20:35 | third | semmle.label | third |
-| test.ps1:21:11:21:17 | first | semmle.label | first |
-| test.ps1:21:21:21:28 | second | semmle.label | second |
-| test.ps1:21:29:21:35 | third | semmle.label | third |
-| test.ps1:22:14:22:21 | second | semmle.label | second |
-| test.ps1:22:22:22:28 | first | semmle.label | first |
-| test.ps1:22:29:22:35 | third | semmle.label | third |
-| test.ps1:23:11:23:18 | second | semmle.label | second |
-| test.ps1:23:22:23:28 | first | semmle.label | first |
-| test.ps1:23:32:23:38 | third | semmle.label | third |
-| test.ps1:24:14:24:20 | first | semmle.label | first |
-| test.ps1:24:21:24:28 | second | semmle.label | second |
-| test.ps1:24:32:24:38 | third | semmle.label | third |
-| test.ps1:25:11:25:17 | first | semmle.label | first |
-| test.ps1:25:21:25:28 | second | semmle.label | second |
-| test.ps1:25:32:25:38 | third | semmle.label | third |
-| test.ps1:26:14:26:21 | second | semmle.label | second |
-| test.ps1:26:22:26:28 | first | semmle.label | first |
-| test.ps1:26:32:26:38 | third | semmle.label | third |
-| test.ps1:27:11:27:18 | second | semmle.label | second |
-| test.ps1:27:22:27:28 | first | semmle.label | first |
-| test.ps1:27:32:27:38 | third | semmle.label | third |
-| test.ps1:28:14:28:20 | first | semmle.label | first |
-| test.ps1:28:24:28:30 | third | semmle.label | third |
-| test.ps1:28:31:28:38 | second | semmle.label | second |
-| test.ps1:29:11:29:17 | first | semmle.label | first |
-| test.ps1:29:21:29:28 | second | semmle.label | second |
-| test.ps1:29:32:29:38 | third | semmle.label | third |
-| test.ps1:30:14:30:21 | second | semmle.label | second |
-| test.ps1:30:25:30:31 | third | semmle.label | third |
-| test.ps1:30:32:30:38 | first | semmle.label | first |
-| test.ps1:31:11:31:18 | second | semmle.label | second |
-| test.ps1:31:22:31:28 | third | semmle.label | third |
-| test.ps1:31:32:31:38 | first | semmle.label | first |
-| test.ps1:32:14:32:20 | first | semmle.label | first |
-| test.ps1:32:24:32:30 | third | semmle.label | third |
-| test.ps1:32:31:32:38 | second | semmle.label | second |
-| test.ps1:33:11:33:17 | first | semmle.label | first |
-| test.ps1:33:21:33:27 | third | semmle.label | third |
-| test.ps1:33:31:33:38 | second | semmle.label | second |
-| test.ps1:34:14:34:21 | second | semmle.label | second |
-| test.ps1:34:25:34:31 | third | semmle.label | third |
-| test.ps1:34:32:34:38 | first | semmle.label | first |
-| test.ps1:35:14:35:20 | third | semmle.label | third |
-| test.ps1:35:24:35:31 | second | semmle.label | second |
-| test.ps1:35:32:35:38 | first | semmle.label | first |
-| test.ps1:36:14:36:20 | third | semmle.label | third |
-| test.ps1:36:21:36:28 | second | semmle.label | second |
-| test.ps1:36:32:36:38 | first | semmle.label | first |
-| test.ps1:37:14:37:20 | third | semmle.label | third |
-| test.ps1:37:24:37:30 | first | semmle.label | first |
-| test.ps1:37:31:37:38 | second | semmle.label | second |
-| test.ps1:38:14:38:20 | third | semmle.label | third |
-| test.ps1:38:21:38:27 | first | semmle.label | first |
-| test.ps1:38:31:38:38 | second | semmle.label | second |
-| test.ps1:39:14:39:20 | third | semmle.label | third |
-| test.ps1:39:24:39:31 | second | semmle.label | second |
-| test.ps1:39:32:39:38 | first | semmle.label | first |
+| global.ps1:1:1:6:32 | Source1 | semmle.label | Source1 |
+| global.ps1:1:1:6:32 | Source2 | semmle.label | Source2 |
+| global.ps1:1:1:6:32 | Source3 | semmle.label | Source3 |
+| global.ps1:1:1:6:32 | Source4 | semmle.label | Source4 |
+| global.ps1:3:6:3:13 | Source1 | semmle.label | Source1 |
+| global.ps1:4:6:4:13 | Source2 | semmle.label | Source2 |
+| global.ps1:5:6:5:13 | Source3 | semmle.label | Source3 |
+| global.ps1:6:6:6:13 | Source4 | semmle.label | Source4 |
+| test.ps1:1:18:3:1 | a | semmle.label | a |
+| test.ps1:2:10:2:11 | a | semmle.label | a |
+| test.ps1:5:6:5:15 | Call to Source | semmle.label | Call to Source |
+| test.ps1:6:5:6:6 | x | semmle.label | x |
+| test.ps1:8:32:12:1 | x | semmle.label | x |
+| test.ps1:8:32:12:1 | y | semmle.label | y |
+| test.ps1:8:32:12:1 | z | semmle.label | z |
+| test.ps1:9:10:9:11 | x | semmle.label | x |
+| test.ps1:10:10:10:11 | y | semmle.label | y |
+| test.ps1:11:10:11:11 | z | semmle.label | z |
+| test.ps1:14:10:14:19 | Call to Source | semmle.label | Call to Source |
+| test.ps1:15:11:15:20 | Call to Source | semmle.label | Call to Source |
+| test.ps1:16:10:16:19 | Call to Source | semmle.label | Call to Source |
+| test.ps1:18:11:18:16 | first | semmle.label | first |
+| test.ps1:18:18:18:24 | second | semmle.label | second |
+| test.ps1:18:26:18:31 | third | semmle.label | third |
+| test.ps1:19:11:19:17 | second | semmle.label | second |
+| test.ps1:19:22:19:27 | first | semmle.label | first |
+| test.ps1:19:29:19:34 | third | semmle.label | third |
+| test.ps1:20:14:20:19 | first | semmle.label | first |
+| test.ps1:20:21:20:27 | second | semmle.label | second |
+| test.ps1:20:29:20:34 | third | semmle.label | third |
+| test.ps1:21:11:21:16 | first | semmle.label | first |
+| test.ps1:21:21:21:27 | second | semmle.label | second |
+| test.ps1:21:29:21:34 | third | semmle.label | third |
+| test.ps1:22:14:22:20 | second | semmle.label | second |
+| test.ps1:22:22:22:27 | first | semmle.label | first |
+| test.ps1:22:29:22:34 | third | semmle.label | third |
+| test.ps1:23:11:23:17 | second | semmle.label | second |
+| test.ps1:23:22:23:27 | first | semmle.label | first |
+| test.ps1:23:32:23:37 | third | semmle.label | third |
+| test.ps1:24:14:24:19 | first | semmle.label | first |
+| test.ps1:24:21:24:27 | second | semmle.label | second |
+| test.ps1:24:32:24:37 | third | semmle.label | third |
+| test.ps1:25:11:25:16 | first | semmle.label | first |
+| test.ps1:25:21:25:27 | second | semmle.label | second |
+| test.ps1:25:32:25:37 | third | semmle.label | third |
+| test.ps1:26:14:26:20 | second | semmle.label | second |
+| test.ps1:26:22:26:27 | first | semmle.label | first |
+| test.ps1:26:32:26:37 | third | semmle.label | third |
+| test.ps1:27:11:27:17 | second | semmle.label | second |
+| test.ps1:27:22:27:27 | first | semmle.label | first |
+| test.ps1:27:32:27:37 | third | semmle.label | third |
+| test.ps1:28:14:28:19 | first | semmle.label | first |
+| test.ps1:28:24:28:29 | third | semmle.label | third |
+| test.ps1:28:31:28:37 | second | semmle.label | second |
+| test.ps1:29:11:29:16 | first | semmle.label | first |
+| test.ps1:29:21:29:27 | second | semmle.label | second |
+| test.ps1:29:32:29:37 | third | semmle.label | third |
+| test.ps1:30:14:30:20 | second | semmle.label | second |
+| test.ps1:30:25:30:30 | third | semmle.label | third |
+| test.ps1:30:32:30:37 | first | semmle.label | first |
+| test.ps1:31:11:31:17 | second | semmle.label | second |
+| test.ps1:31:22:31:27 | third | semmle.label | third |
+| test.ps1:31:32:31:37 | first | semmle.label | first |
+| test.ps1:32:14:32:19 | first | semmle.label | first |
+| test.ps1:32:24:32:29 | third | semmle.label | third |
+| test.ps1:32:31:32:37 | second | semmle.label | second |
+| test.ps1:33:11:33:16 | first | semmle.label | first |
+| test.ps1:33:21:33:26 | third | semmle.label | third |
+| test.ps1:33:31:33:37 | second | semmle.label | second |
+| test.ps1:34:14:34:20 | second | semmle.label | second |
+| test.ps1:34:25:34:30 | third | semmle.label | third |
+| test.ps1:34:32:34:37 | first | semmle.label | first |
+| test.ps1:35:14:35:19 | third | semmle.label | third |
+| test.ps1:35:24:35:30 | second | semmle.label | second |
+| test.ps1:35:32:35:37 | first | semmle.label | first |
+| test.ps1:36:14:36:19 | third | semmle.label | third |
+| test.ps1:36:21:36:27 | second | semmle.label | second |
+| test.ps1:36:32:36:37 | first | semmle.label | first |
+| test.ps1:37:14:37:19 | third | semmle.label | third |
+| test.ps1:37:24:37:29 | first | semmle.label | first |
+| test.ps1:37:31:37:37 | second | semmle.label | second |
+| test.ps1:38:14:38:19 | third | semmle.label | third |
+| test.ps1:38:21:38:26 | first | semmle.label | first |
+| test.ps1:38:31:38:37 | second | semmle.label | second |
+| test.ps1:39:14:39:19 | third | semmle.label | third |
+| test.ps1:39:24:39:30 | second | semmle.label | second |
+| test.ps1:39:32:39:37 | first | semmle.label | first |
subpaths
testFailures
#select
-| global.ps1:3:6:3:14 | Source1 | global.ps1:1:7:1:23 | Source1 | global.ps1:3:6:3:14 | Source1 | $@ | global.ps1:1:7:1:23 | Source1 | Source1 |
-| global.ps1:4:6:4:14 | Source2 | global.ps1:1:25:1:41 | Source2 | global.ps1:4:6:4:14 | Source2 | $@ | global.ps1:1:25:1:41 | Source2 | Source2 |
-| global.ps1:5:6:5:14 | Source3 | global.ps1:1:43:1:59 | Source3 | global.ps1:5:6:5:14 | Source3 | $@ | global.ps1:1:43:1:59 | Source3 | Source3 |
-| global.ps1:6:6:6:14 | Source4 | global.ps1:1:61:1:77 | Source4 | global.ps1:6:6:6:14 | Source4 | $@ | global.ps1:1:61:1:77 | Source4 | Source4 |
-| test.ps1:2:10:2:12 | a | test.ps1:5:6:5:16 | call to Source | test.ps1:2:10:2:12 | a | $@ | test.ps1:5:6:5:16 | call to Source | call to Source |
-| test.ps1:9:10:9:12 | x | test.ps1:14:10:14:20 | call to Source | test.ps1:9:10:9:12 | x | $@ | test.ps1:14:10:14:20 | call to Source | call to Source |
-| test.ps1:10:10:10:12 | y | test.ps1:15:11:15:21 | call to Source | test.ps1:10:10:10:12 | y | $@ | test.ps1:15:11:15:21 | call to Source | call to Source |
-| test.ps1:11:10:11:12 | z | test.ps1:16:10:16:20 | call to Source | test.ps1:11:10:11:12 | z | $@ | test.ps1:16:10:16:20 | call to Source | call to Source |
+| global.ps1:3:6:3:13 | Source1 | global.ps1:1:1:6:32 | Source1 | global.ps1:3:6:3:13 | Source1 | $@ | global.ps1:1:1:6:32 | Source1 | Source1 |
+| global.ps1:4:6:4:13 | Source2 | global.ps1:1:1:6:32 | Source2 | global.ps1:4:6:4:13 | Source2 | $@ | global.ps1:1:1:6:32 | Source2 | Source2 |
+| global.ps1:5:6:5:13 | Source3 | global.ps1:1:1:6:32 | Source3 | global.ps1:5:6:5:13 | Source3 | $@ | global.ps1:1:1:6:32 | Source3 | Source3 |
+| global.ps1:6:6:6:13 | Source4 | global.ps1:1:1:6:32 | Source4 | global.ps1:6:6:6:13 | Source4 | $@ | global.ps1:1:1:6:32 | Source4 | Source4 |
+| test.ps1:2:10:2:11 | a | test.ps1:5:6:5:15 | Call to Source | test.ps1:2:10:2:11 | a | $@ | test.ps1:5:6:5:15 | Call to Source | Call to Source |
+| test.ps1:9:10:9:11 | x | test.ps1:14:10:14:19 | Call to Source | test.ps1:9:10:9:11 | x | $@ | test.ps1:14:10:14:19 | Call to Source | Call to Source |
+| test.ps1:10:10:10:11 | y | test.ps1:15:11:15:20 | Call to Source | test.ps1:10:10:10:11 | y | $@ | test.ps1:15:11:15:20 | Call to Source | Call to Source |
+| test.ps1:11:10:11:11 | z | test.ps1:16:10:16:19 | Call to Source | test.ps1:11:10:11:11 | z | $@ | test.ps1:16:10:16:19 | Call to Source | Call to Source |
diff --git a/powershell/ql/test/library-tests/dataflow/pipeline/test.expected b/powershell/ql/test/library-tests/dataflow/pipeline/test.expected
index 12b6de837cb2..bbea92282028 100644
--- a/powershell/ql/test/library-tests/dataflow/pipeline/test.expected
+++ b/powershell/ql/test/library-tests/dataflow/pipeline/test.expected
@@ -1,127 +1,17 @@
models
edges
-| test.ps1:2:10:2:20 | call to Source | test.ps1:5:5:5:7 | x | provenance | |
-| test.ps1:3:10:3:20 | call to Source | test.ps1:6:5:6:7 | y | provenance | |
-| test.ps1:4:10:4:20 | call to Source | test.ps1:6:9:6:11 | z | provenance | |
-| test.ps1:5:5:5:7 | x | test.ps1:17:1:17:8 | call to produce [element] | provenance | |
-| test.ps1:6:5:6:7 | y | test.ps1:6:5:6:11 | ...,... [element 0] | provenance | |
-| test.ps1:6:5:6:11 | ...,... [element 0] | test.ps1:17:1:17:8 | call to produce [element] | provenance | |
-| test.ps1:6:5:6:11 | ...,... [element 1] | test.ps1:17:1:17:8 | call to produce [element] | provenance | |
-| test.ps1:6:9:6:11 | z | test.ps1:6:5:6:11 | ...,... [element 1] | provenance | |
-| test.ps1:10:11:10:44 | x [element 0] | test.ps1:13:14:13:16 | x | provenance | |
-| test.ps1:10:11:10:44 | x [element 1] | test.ps1:13:14:13:16 | x | provenance | |
-| test.ps1:10:11:10:44 | x [element] | test.ps1:13:14:13:16 | x | provenance | |
-| test.ps1:17:1:17:8 | call to produce [element] | test.ps1:10:11:10:44 | x [element] | provenance | |
-| test.ps1:19:6:19:16 | call to Source | test.ps1:21:1:21:3 | x | provenance | |
-| test.ps1:20:6:20:16 | call to Source | test.ps1:21:5:21:7 | y | provenance | |
-| test.ps1:21:1:21:3 | x | test.ps1:21:1:21:7 | ...,... [element 0] | provenance | |
-| test.ps1:21:1:21:7 | ...,... [element 0] | test.ps1:10:11:10:44 | x [element 0] | provenance | |
-| test.ps1:21:1:21:7 | ...,... [element 0] | test.ps1:21:1:21:7 | ...,... [element 0] | provenance | |
-| test.ps1:21:1:21:7 | ...,... [element 1] | test.ps1:10:11:10:44 | x [element 1] | provenance | |
-| test.ps1:21:1:21:7 | ...,... [element 1] | test.ps1:21:1:21:7 | ...,... [element 1] | provenance | |
-| test.ps1:21:5:21:7 | y | test.ps1:21:1:21:7 | ...,... [element 1] | provenance | |
-| test.ps1:25:14:25:16 | _ [element 0] | test.ps1:25:14:25:16 | _ | provenance | |
-| test.ps1:25:14:25:16 | _ [element 1] | test.ps1:25:14:25:16 | _ | provenance | |
-| test.ps1:29:6:29:16 | call to Source | test.ps1:31:1:31:3 | x | provenance | |
-| test.ps1:30:6:30:16 | call to Source | test.ps1:31:5:31:7 | y | provenance | |
-| test.ps1:31:1:31:3 | x | test.ps1:31:1:31:7 | ...,... [element 0] | provenance | |
-| test.ps1:31:1:31:7 | ...,... [element 0] | test.ps1:25:14:25:16 | _ [element 0] | provenance | |
-| test.ps1:31:1:31:7 | ...,... [element 0] | test.ps1:31:1:31:7 | ...,... [element 0] | provenance | |
-| test.ps1:31:1:31:7 | ...,... [element 1] | test.ps1:25:14:25:16 | _ [element 1] | provenance | |
-| test.ps1:31:1:31:7 | ...,... [element 1] | test.ps1:31:1:31:7 | ...,... [element 1] | provenance | |
-| test.ps1:31:5:31:7 | y | test.ps1:31:1:31:7 | ...,... [element 1] | provenance | |
-| test.ps1:34:11:34:58 | x [element x] | test.ps1:36:10:36:12 | x | provenance | |
-| test.ps1:39:6:39:16 | call to Source | test.ps1:40:23:40:25 | x | provenance | |
-| test.ps1:40:1:40:26 | [...]... [element x] | test.ps1:34:11:34:58 | x [element x] | provenance | |
-| test.ps1:40:17:40:26 | ${...} [element x] | test.ps1:40:1:40:26 | [...]... [element x] | provenance | |
-| test.ps1:40:23:40:25 | x | test.ps1:40:17:40:26 | ${...} [element x] | provenance | |
-| test.ps1:43:11:43:58 | x [element 0, element x] | test.ps1:46:14:46:16 | x | provenance | |
-| test.ps1:43:11:43:58 | x [element 1, element x] | test.ps1:46:14:46:16 | x | provenance | |
-| test.ps1:43:11:43:58 | x [element 2, element x] | test.ps1:46:14:46:16 | x | provenance | |
-| test.ps1:50:1:50:34 | [...]... [element x] | test.ps1:50:1:50:106 | ...,... [element 0, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 0, element x] | test.ps1:43:11:43:58 | x [element 0, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 0, element x] | test.ps1:50:1:50:106 | ...,... [element 0, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 1, element x] | test.ps1:43:11:43:58 | x [element 1, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 1, element x] | test.ps1:50:1:50:106 | ...,... [element 1, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 2, element x] | test.ps1:43:11:43:58 | x [element 2, element x] | provenance | |
-| test.ps1:50:1:50:106 | ...,... [element 2, element x] | test.ps1:50:1:50:106 | ...,... [element 2, element x] | provenance | |
-| test.ps1:50:17:50:34 | ${...} [element x] | test.ps1:50:1:50:34 | [...]... [element x] | provenance | |
-| test.ps1:50:23:50:33 | call to Source | test.ps1:50:17:50:34 | ${...} [element x] | provenance | |
-| test.ps1:50:36:50:70 | [...]... [element x] | test.ps1:50:1:50:106 | ...,... [element 1, element x] | provenance | |
-| test.ps1:50:52:50:70 | ${...} [element x] | test.ps1:50:36:50:70 | [...]... [element x] | provenance | |
-| test.ps1:50:58:50:69 | call to Source | test.ps1:50:52:50:70 | ${...} [element x] | provenance | |
-| test.ps1:50:72:50:106 | [...]... [element x] | test.ps1:50:1:50:106 | ...,... [element 2, element x] | provenance | |
-| test.ps1:50:88:50:106 | ${...} [element x] | test.ps1:50:72:50:106 | [...]... [element x] | provenance | |
-| test.ps1:50:94:50:105 | call to Source | test.ps1:50:88:50:106 | ${...} [element x] | provenance | |
nodes
-| test.ps1:2:10:2:20 | call to Source | semmle.label | call to Source |
-| test.ps1:3:10:3:20 | call to Source | semmle.label | call to Source |
-| test.ps1:4:10:4:20 | call to Source | semmle.label | call to Source |
-| test.ps1:5:5:5:7 | x | semmle.label | x |
-| test.ps1:6:5:6:7 | y | semmle.label | y |
-| test.ps1:6:5:6:11 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:6:5:6:11 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:6:9:6:11 | z | semmle.label | z |
-| test.ps1:10:11:10:44 | x [element 0] | semmle.label | x [element 0] |
-| test.ps1:10:11:10:44 | x [element 1] | semmle.label | x [element 1] |
-| test.ps1:10:11:10:44 | x [element] | semmle.label | x [element] |
-| test.ps1:13:14:13:16 | x | semmle.label | x |
-| test.ps1:17:1:17:8 | call to produce [element] | semmle.label | call to produce [element] |
-| test.ps1:19:6:19:16 | call to Source | semmle.label | call to Source |
-| test.ps1:20:6:20:16 | call to Source | semmle.label | call to Source |
-| test.ps1:21:1:21:3 | x | semmle.label | x |
-| test.ps1:21:1:21:7 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:21:1:21:7 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:21:1:21:7 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:21:1:21:7 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:21:5:21:7 | y | semmle.label | y |
-| test.ps1:25:14:25:16 | _ | semmle.label | _ |
-| test.ps1:25:14:25:16 | _ [element 0] | semmle.label | _ [element 0] |
-| test.ps1:25:14:25:16 | _ [element 1] | semmle.label | _ [element 1] |
-| test.ps1:29:6:29:16 | call to Source | semmle.label | call to Source |
-| test.ps1:30:6:30:16 | call to Source | semmle.label | call to Source |
-| test.ps1:31:1:31:3 | x | semmle.label | x |
-| test.ps1:31:1:31:7 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:31:1:31:7 | ...,... [element 0] | semmle.label | ...,... [element 0] |
-| test.ps1:31:1:31:7 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:31:1:31:7 | ...,... [element 1] | semmle.label | ...,... [element 1] |
-| test.ps1:31:5:31:7 | y | semmle.label | y |
-| test.ps1:34:11:34:58 | x [element x] | semmle.label | x [element x] |
-| test.ps1:36:10:36:12 | x | semmle.label | x |
-| test.ps1:39:6:39:16 | call to Source | semmle.label | call to Source |
-| test.ps1:40:1:40:26 | [...]... [element x] | semmle.label | [...]... [element x] |
-| test.ps1:40:17:40:26 | ${...} [element x] | semmle.label | ${...} [element x] |
-| test.ps1:40:23:40:25 | x | semmle.label | x |
-| test.ps1:43:11:43:58 | x [element 0, element x] | semmle.label | x [element 0, element x] |
-| test.ps1:43:11:43:58 | x [element 1, element x] | semmle.label | x [element 1, element x] |
-| test.ps1:43:11:43:58 | x [element 2, element x] | semmle.label | x [element 2, element x] |
-| test.ps1:46:14:46:16 | x | semmle.label | x |
-| test.ps1:50:1:50:34 | [...]... [element x] | semmle.label | [...]... [element x] |
-| test.ps1:50:1:50:106 | ...,... [element 0, element x] | semmle.label | ...,... [element 0, element x] |
-| test.ps1:50:1:50:106 | ...,... [element 0, element x] | semmle.label | ...,... [element 0, element x] |
-| test.ps1:50:1:50:106 | ...,... [element 1, element x] | semmle.label | ...,... [element 1, element x] |
-| test.ps1:50:1:50:106 | ...,... [element 1, element x] | semmle.label | ...,... [element 1, element x] |
-| test.ps1:50:1:50:106 | ...,... [element 2, element x] | semmle.label | ...,... [element 2, element x] |
-| test.ps1:50:1:50:106 | ...,... [element 2, element x] | semmle.label | ...,... [element 2, element x] |
-| test.ps1:50:17:50:34 | ${...} [element x] | semmle.label | ${...} [element x] |
-| test.ps1:50:23:50:33 | call to Source | semmle.label | call to Source |
-| test.ps1:50:36:50:70 | [...]... [element x] | semmle.label | [...]... [element x] |
-| test.ps1:50:52:50:70 | ${...} [element x] | semmle.label | ${...} [element x] |
-| test.ps1:50:58:50:69 | call to Source | semmle.label | call to Source |
-| test.ps1:50:72:50:106 | [...]... [element x] | semmle.label | [...]... [element x] |
-| test.ps1:50:88:50:106 | ${...} [element x] | semmle.label | ${...} [element x] |
-| test.ps1:50:94:50:105 | call to Source | semmle.label | call to Source |
subpaths
testFailures
+| test.ps1:13:17:13:94 | # $ hasValueFlow=1 hasValueFlow=2 hasValueFlow=3 hasValueFlow=4 hasValueFlow=5 | Missing result: hasValueFlow=1 |
+| test.ps1:13:17:13:94 | # $ hasValueFlow=1 hasValueFlow=2 hasValueFlow=3 hasValueFlow=4 hasValueFlow=5 | Missing result: hasValueFlow=2 |
+| test.ps1:13:17:13:94 | # $ hasValueFlow=1 hasValueFlow=2 hasValueFlow=3 hasValueFlow=4 hasValueFlow=5 | Missing result: hasValueFlow=3 |
+| test.ps1:13:17:13:94 | # $ hasValueFlow=1 hasValueFlow=2 hasValueFlow=3 hasValueFlow=4 hasValueFlow=5 | Missing result: hasValueFlow=4 |
+| test.ps1:13:17:13:94 | # $ hasValueFlow=1 hasValueFlow=2 hasValueFlow=3 hasValueFlow=4 hasValueFlow=5 | Missing result: hasValueFlow=5 |
+| test.ps1:25:17:25:49 | # $ hasValueFlow=6 hasValueFlow=7 | Missing result: hasValueFlow=6 |
+| test.ps1:25:17:25:49 | # $ hasValueFlow=6 hasValueFlow=7 | Missing result: hasValueFlow=7 |
+| test.ps1:36:13:36:30 | # $ hasValueFlow=8 | Missing result: hasValueFlow=8 |
+| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=9 |
+| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=10 |
+| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=11 |
#select
-| test.ps1:13:14:13:16 | x | test.ps1:2:10:2:20 | call to Source | test.ps1:13:14:13:16 | x | $@ | test.ps1:2:10:2:20 | call to Source | call to Source |
-| test.ps1:13:14:13:16 | x | test.ps1:3:10:3:20 | call to Source | test.ps1:13:14:13:16 | x | $@ | test.ps1:3:10:3:20 | call to Source | call to Source |
-| test.ps1:13:14:13:16 | x | test.ps1:4:10:4:20 | call to Source | test.ps1:13:14:13:16 | x | $@ | test.ps1:4:10:4:20 | call to Source | call to Source |
-| test.ps1:13:14:13:16 | x | test.ps1:19:6:19:16 | call to Source | test.ps1:13:14:13:16 | x | $@ | test.ps1:19:6:19:16 | call to Source | call to Source |
-| test.ps1:13:14:13:16 | x | test.ps1:20:6:20:16 | call to Source | test.ps1:13:14:13:16 | x | $@ | test.ps1:20:6:20:16 | call to Source | call to Source |
-| test.ps1:25:14:25:16 | _ | test.ps1:29:6:29:16 | call to Source | test.ps1:25:14:25:16 | _ | $@ | test.ps1:29:6:29:16 | call to Source | call to Source |
-| test.ps1:25:14:25:16 | _ | test.ps1:30:6:30:16 | call to Source | test.ps1:25:14:25:16 | _ | $@ | test.ps1:30:6:30:16 | call to Source | call to Source |
-| test.ps1:36:10:36:12 | x | test.ps1:39:6:39:16 | call to Source | test.ps1:36:10:36:12 | x | $@ | test.ps1:39:6:39:16 | call to Source | call to Source |
-| test.ps1:46:14:46:16 | x | test.ps1:50:23:50:33 | call to Source | test.ps1:46:14:46:16 | x | $@ | test.ps1:50:23:50:33 | call to Source | call to Source |
-| test.ps1:46:14:46:16 | x | test.ps1:50:58:50:69 | call to Source | test.ps1:46:14:46:16 | x | $@ | test.ps1:50:58:50:69 | call to Source | call to Source |
-| test.ps1:46:14:46:16 | x | test.ps1:50:94:50:105 | call to Source | test.ps1:46:14:46:16 | x | $@ | test.ps1:50:94:50:105 | call to Source | call to Source |
diff --git a/powershell/ql/test/library-tests/dataflow/returns/test.expected b/powershell/ql/test/library-tests/dataflow/returns/test.expected
index 3fe33326ac75..ae3eefed04d1 100644
--- a/powershell/ql/test/library-tests/dataflow/returns/test.expected
+++ b/powershell/ql/test/library-tests/dataflow/returns/test.expected
@@ -1,69 +1,47 @@
models
edges
-| test.ps1:2:5:2:15 | call to Source | test.ps1:5:6:5:20 | call to callSourceOnce | provenance | |
-| test.ps1:5:6:5:20 | call to callSourceOnce | test.ps1:6:6:6:8 | x | provenance | |
-| test.ps1:9:5:9:15 | call to Source | test.ps1:13:6:13:21 | call to callSourceTwice [element] | provenance | |
-| test.ps1:10:5:10:15 | call to Source | test.ps1:13:6:13:21 | call to callSourceTwice [element] | provenance | |
-| test.ps1:13:6:13:21 | call to callSourceTwice [element] | test.ps1:15:6:15:8 | x [element] | provenance | |
-| test.ps1:13:6:13:21 | call to callSourceTwice [element] | test.ps1:16:6:16:8 | x [element] | provenance | |
-| test.ps1:15:6:15:8 | x [element] | test.ps1:15:6:15:11 | ...[...] | provenance | |
-| test.ps1:16:6:16:8 | x [element] | test.ps1:16:6:16:11 | ...[...] | provenance | |
-| test.ps1:19:12:19:22 | call to Source | test.ps1:22:6:22:19 | call to returnSource1 | provenance | |
-| test.ps1:22:6:22:19 | call to returnSource1 | test.ps1:23:6:23:8 | x | provenance | |
-| test.ps1:26:10:26:20 | call to Source | test.ps1:27:5:27:7 | x | provenance | |
-| test.ps1:27:5:27:7 | x | test.ps1:32:6:32:19 | call to returnSource2 [element] | provenance | |
-| test.ps1:28:10:28:20 | call to Source | test.ps1:29:12:29:14 | y | provenance | |
-| test.ps1:29:12:29:14 | y | test.ps1:32:6:32:19 | call to returnSource2 [element] | provenance | |
-| test.ps1:32:6:32:19 | call to returnSource2 [element] | test.ps1:33:6:33:8 | x [element] | provenance | |
-| test.ps1:32:6:32:19 | call to returnSource2 [element] | test.ps1:34:6:34:8 | x [element] | provenance | |
-| test.ps1:33:6:33:8 | x [element] | test.ps1:33:6:33:11 | ...[...] | provenance | |
-| test.ps1:34:6:34:8 | x [element] | test.ps1:34:6:34:11 | ...[...] | provenance | |
-| test.ps1:38:9:38:19 | call to Source | test.ps1:42:6:42:22 | call to callSourceInLoop [element] | provenance | |
-| test.ps1:42:6:42:22 | call to callSourceInLoop [element] | test.ps1:43:6:43:8 | x [element] | provenance | |
-| test.ps1:42:6:42:22 | call to callSourceInLoop [element] | test.ps1:44:6:44:8 | x [element] | provenance | |
-| test.ps1:43:6:43:8 | x [element] | test.ps1:43:6:43:11 | ...[...] | provenance | |
-| test.ps1:44:6:44:8 | x [element] | test.ps1:44:6:44:11 | ...[...] | provenance | |
+| test.ps1:2:5:2:14 | Call to Source | test.ps1:5:6:5:19 | Call to callSourceOnce | provenance | |
+| test.ps1:5:6:5:19 | Call to callSourceOnce | test.ps1:6:6:6:7 | x | provenance | |
+| test.ps1:9:5:9:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [element] | provenance | |
+| test.ps1:10:5:10:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [element] | provenance | |
+| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | test.ps1:15:6:15:7 | x [element] | provenance | |
+| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | test.ps1:16:6:16:7 | x [element] | provenance | |
+| test.ps1:15:6:15:7 | x [element] | test.ps1:15:6:15:10 | ...[...] | provenance | |
+| test.ps1:16:6:16:7 | x [element] | test.ps1:16:6:16:10 | ...[...] | provenance | |
+| test.ps1:38:9:38:18 | Call to Source | test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | provenance | |
+| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | test.ps1:43:6:43:7 | x [element] | provenance | |
+| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | test.ps1:44:6:44:7 | x [element] | provenance | |
+| test.ps1:43:6:43:7 | x [element] | test.ps1:43:6:43:10 | ...[...] | provenance | |
+| test.ps1:44:6:44:7 | x [element] | test.ps1:44:6:44:10 | ...[...] | provenance | |
nodes
-| test.ps1:2:5:2:15 | call to Source | semmle.label | call to Source |
-| test.ps1:5:6:5:20 | call to callSourceOnce | semmle.label | call to callSourceOnce |
-| test.ps1:6:6:6:8 | x | semmle.label | x |
-| test.ps1:9:5:9:15 | call to Source | semmle.label | call to Source |
-| test.ps1:10:5:10:15 | call to Source | semmle.label | call to Source |
-| test.ps1:13:6:13:21 | call to callSourceTwice [element] | semmle.label | call to callSourceTwice [element] |
-| test.ps1:15:6:15:8 | x [element] | semmle.label | x [element] |
-| test.ps1:15:6:15:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:16:6:16:8 | x [element] | semmle.label | x [element] |
-| test.ps1:16:6:16:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:19:12:19:22 | call to Source | semmle.label | call to Source |
-| test.ps1:22:6:22:19 | call to returnSource1 | semmle.label | call to returnSource1 |
-| test.ps1:23:6:23:8 | x | semmle.label | x |
-| test.ps1:26:10:26:20 | call to Source | semmle.label | call to Source |
-| test.ps1:27:5:27:7 | x | semmle.label | x |
-| test.ps1:28:10:28:20 | call to Source | semmle.label | call to Source |
-| test.ps1:29:12:29:14 | y | semmle.label | y |
-| test.ps1:32:6:32:19 | call to returnSource2 [element] | semmle.label | call to returnSource2 [element] |
-| test.ps1:33:6:33:8 | x [element] | semmle.label | x [element] |
-| test.ps1:33:6:33:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:34:6:34:8 | x [element] | semmle.label | x [element] |
-| test.ps1:34:6:34:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:38:9:38:19 | call to Source | semmle.label | call to Source |
-| test.ps1:42:6:42:22 | call to callSourceInLoop [element] | semmle.label | call to callSourceInLoop [element] |
-| test.ps1:43:6:43:8 | x [element] | semmle.label | x [element] |
-| test.ps1:43:6:43:11 | ...[...] | semmle.label | ...[...] |
-| test.ps1:44:6:44:8 | x [element] | semmle.label | x [element] |
-| test.ps1:44:6:44:11 | ...[...] | semmle.label | ...[...] |
+| test.ps1:2:5:2:14 | Call to Source | semmle.label | Call to Source |
+| test.ps1:5:6:5:19 | Call to callSourceOnce | semmle.label | Call to callSourceOnce |
+| test.ps1:6:6:6:7 | x | semmle.label | x |
+| test.ps1:9:5:9:14 | Call to Source | semmle.label | Call to Source |
+| test.ps1:10:5:10:14 | Call to Source | semmle.label | Call to Source |
+| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | semmle.label | Call to callSourceTwice [element] |
+| test.ps1:15:6:15:7 | x [element] | semmle.label | x [element] |
+| test.ps1:15:6:15:10 | ...[...] | semmle.label | ...[...] |
+| test.ps1:16:6:16:7 | x [element] | semmle.label | x [element] |
+| test.ps1:16:6:16:10 | ...[...] | semmle.label | ...[...] |
+| test.ps1:38:9:38:18 | Call to Source | semmle.label | Call to Source |
+| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | semmle.label | Call to callSourceInLoop [element] |
+| test.ps1:43:6:43:7 | x [element] | semmle.label | x [element] |
+| test.ps1:43:6:43:10 | ...[...] | semmle.label | ...[...] |
+| test.ps1:44:6:44:7 | x [element] | semmle.label | x [element] |
+| test.ps1:44:6:44:10 | ...[...] | semmle.label | ...[...] |
subpaths
testFailures
+| test.ps1:23:9:23:26 | # $ hasValueFlow=4 | Missing result: hasValueFlow=4 |
+| test.ps1:33:12:33:54 | # $ hasValueFlow=5 SPURIOUS: hasValueFlow=6 | Fixed spurious result: hasValueFlow=6 |
+| test.ps1:33:12:33:54 | # $ hasValueFlow=5 SPURIOUS: hasValueFlow=6 | Missing result: hasValueFlow=5 |
+| test.ps1:34:12:34:54 | # $ hasValueFlow=6 SPURIOUS: hasValueFlow=5 | Fixed spurious result: hasValueFlow=5 |
+| test.ps1:34:12:34:54 | # $ hasValueFlow=6 SPURIOUS: hasValueFlow=5 | Missing result: hasValueFlow=6 |
#select
-| test.ps1:6:6:6:8 | x | test.ps1:2:5:2:15 | call to Source | test.ps1:6:6:6:8 | x | $@ | test.ps1:2:5:2:15 | call to Source | call to Source |
-| test.ps1:15:6:15:11 | ...[...] | test.ps1:9:5:9:15 | call to Source | test.ps1:15:6:15:11 | ...[...] | $@ | test.ps1:9:5:9:15 | call to Source | call to Source |
-| test.ps1:15:6:15:11 | ...[...] | test.ps1:10:5:10:15 | call to Source | test.ps1:15:6:15:11 | ...[...] | $@ | test.ps1:10:5:10:15 | call to Source | call to Source |
-| test.ps1:16:6:16:11 | ...[...] | test.ps1:9:5:9:15 | call to Source | test.ps1:16:6:16:11 | ...[...] | $@ | test.ps1:9:5:9:15 | call to Source | call to Source |
-| test.ps1:16:6:16:11 | ...[...] | test.ps1:10:5:10:15 | call to Source | test.ps1:16:6:16:11 | ...[...] | $@ | test.ps1:10:5:10:15 | call to Source | call to Source |
-| test.ps1:23:6:23:8 | x | test.ps1:19:12:19:22 | call to Source | test.ps1:23:6:23:8 | x | $@ | test.ps1:19:12:19:22 | call to Source | call to Source |
-| test.ps1:33:6:33:11 | ...[...] | test.ps1:26:10:26:20 | call to Source | test.ps1:33:6:33:11 | ...[...] | $@ | test.ps1:26:10:26:20 | call to Source | call to Source |
-| test.ps1:33:6:33:11 | ...[...] | test.ps1:28:10:28:20 | call to Source | test.ps1:33:6:33:11 | ...[...] | $@ | test.ps1:28:10:28:20 | call to Source | call to Source |
-| test.ps1:34:6:34:11 | ...[...] | test.ps1:26:10:26:20 | call to Source | test.ps1:34:6:34:11 | ...[...] | $@ | test.ps1:26:10:26:20 | call to Source | call to Source |
-| test.ps1:34:6:34:11 | ...[...] | test.ps1:28:10:28:20 | call to Source | test.ps1:34:6:34:11 | ...[...] | $@ | test.ps1:28:10:28:20 | call to Source | call to Source |
-| test.ps1:43:6:43:11 | ...[...] | test.ps1:38:9:38:19 | call to Source | test.ps1:43:6:43:11 | ...[...] | $@ | test.ps1:38:9:38:19 | call to Source | call to Source |
-| test.ps1:44:6:44:11 | ...[...] | test.ps1:38:9:38:19 | call to Source | test.ps1:44:6:44:11 | ...[...] | $@ | test.ps1:38:9:38:19 | call to Source | call to Source |
+| test.ps1:6:6:6:7 | x | test.ps1:2:5:2:14 | Call to Source | test.ps1:6:6:6:7 | x | $@ | test.ps1:2:5:2:14 | Call to Source | Call to Source |
+| test.ps1:15:6:15:10 | ...[...] | test.ps1:9:5:9:14 | Call to Source | test.ps1:15:6:15:10 | ...[...] | $@ | test.ps1:9:5:9:14 | Call to Source | Call to Source |
+| test.ps1:15:6:15:10 | ...[...] | test.ps1:10:5:10:14 | Call to Source | test.ps1:15:6:15:10 | ...[...] | $@ | test.ps1:10:5:10:14 | Call to Source | Call to Source |
+| test.ps1:16:6:16:10 | ...[...] | test.ps1:9:5:9:14 | Call to Source | test.ps1:16:6:16:10 | ...[...] | $@ | test.ps1:9:5:9:14 | Call to Source | Call to Source |
+| test.ps1:16:6:16:10 | ...[...] | test.ps1:10:5:10:14 | Call to Source | test.ps1:16:6:16:10 | ...[...] | $@ | test.ps1:10:5:10:14 | Call to Source | Call to Source |
+| test.ps1:43:6:43:10 | ...[...] | test.ps1:38:9:38:18 | Call to Source | test.ps1:43:6:43:10 | ...[...] | $@ | test.ps1:38:9:38:18 | Call to Source | Call to Source |
+| test.ps1:44:6:44:10 | ...[...] | test.ps1:38:9:38:18 | Call to Source | test.ps1:44:6:44:10 | ...[...] | $@ | test.ps1:38:9:38:18 | Call to Source | Call to Source |
diff --git a/powershell/ql/test/library-tests/dataflow/typetracking/test.expected b/powershell/ql/test/library-tests/dataflow/typetracking/test.expected
index 8ec8033d086e..8748ef879ad2 100644
--- a/powershell/ql/test/library-tests/dataflow/typetracking/test.expected
+++ b/powershell/ql/test/library-tests/dataflow/typetracking/test.expected
@@ -1,2 +1,2 @@
-testFailures
-failures
+| test.ps1:15:20:15:36 | # $ type=PSObject | Missing result: type=PSObject |
+| test.ps1:19:25:19:41 | # $ type=PSObject | Missing result: type=PSObject |
diff --git a/powershell/ql/test/library-tests/ssa/ssa.expected b/powershell/ql/test/library-tests/ssa/ssa.expected
index 3dc5c8e4c07f..1cfa0788bbc6 100644
--- a/powershell/ql/test/library-tests/ssa/ssa.expected
+++ b/powershell/ql/test/library-tests/ssa/ssa.expected
@@ -1,7 +1,6 @@
-| explicit.ps1:1:1:8:2 | glob_a | explicit.ps1:2:11:2:18 | glob_a |
-| explicit.ps1:5:5:5:7 | a | explicit.ps1:5:5:5:7 | a |
-| explicit.ps1:6:5:6:7 | b | explicit.ps1:6:5:6:7 | b |
-| parameters.ps1:1:25:1:33 | n1 | parameters.ps1:1:25:1:33 | n1 |
-| parameters.ps1:1:35:1:43 | n2 | parameters.ps1:1:35:1:43 | n2 |
-| parameters.ps1:7:9:7:16 | a | parameters.ps1:7:9:7:16 | a |
-| parameters.ps1:8:9:8:16 | b | parameters.ps1:8:9:8:16 | b |
+| explicit.ps1:5:5:5:6 | a | explicit.ps1:5:5:5:6 | a |
+| explicit.ps1:6:5:6:6 | b | explicit.ps1:6:5:6:6 | b |
+| parameters.ps1:1:45:3:1 | n1 | parameters.ps1:1:45:3:1 | n1 |
+| parameters.ps1:1:45:3:1 | n2 | parameters.ps1:1:45:3:1 | n2 |
+| parameters.ps1:5:22:11:1 | a | parameters.ps1:5:22:11:1 | a |
+| parameters.ps1:5:22:11:1 | b | parameters.ps1:5:22:11:1 | b |
diff --git a/powershell/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected b/powershell/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected
index 53e66a64f682..e217064d1dfc 100644
--- a/powershell/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected
+++ b/powershell/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected
@@ -1,12 +1,4 @@
edges
-| test.ps1:1:8:1:10 | x | test.ps1:3:28:3:48 | Get-Process -Id $x | provenance | |
-| test.ps1:5:10:5:21 | Env:MY_VAR | test.ps1:7:3:7:20 | $code --enabled | provenance | |
nodes
-| test.ps1:1:8:1:10 | x | semmle.label | x |
-| test.ps1:3:28:3:48 | Get-Process -Id $x | semmle.label | Get-Process -Id $x |
-| test.ps1:5:10:5:21 | Env:MY_VAR | semmle.label | Env:MY_VAR |
-| test.ps1:7:3:7:20 | $code --enabled | semmle.label | $code --enabled |
subpaths
#select
-| test.ps1:3:28:3:48 | Get-Process -Id $x | test.ps1:1:8:1:10 | x | test.ps1:3:28:3:48 | Get-Process -Id $x | This command depends on a $@. | test.ps1:1:8:1:10 | x | user-provided value |
-| test.ps1:7:3:7:20 | $code --enabled | test.ps1:5:10:5:21 | Env:MY_VAR | test.ps1:7:3:7:20 | $code --enabled | This command depends on a $@. | test.ps1:5:10:5:21 | Env:MY_VAR | user-provided value |
diff --git a/powershell/ql/test/query-tests/security/cwe-078/DoNotUseInvokeExpression/DoNotUseInvokeExpression.expected b/powershell/ql/test/query-tests/security/cwe-078/DoNotUseInvokeExpression/DoNotUseInvokeExpression.expected
index 3b7235e641f0..738c250420e5 100644
--- a/powershell/ql/test/query-tests/security/cwe-078/DoNotUseInvokeExpression/DoNotUseInvokeExpression.expected
+++ b/powershell/ql/test/query-tests/security/cwe-078/DoNotUseInvokeExpression/DoNotUseInvokeExpression.expected
@@ -1 +1 @@
-| test.ps1:2:1:2:27 | call to Invoke-Expression | Do not use Invoke-Expression. It is a command injection risk. |
+| test.ps1:2:1:2:26 | Call to Invoke-Expression | Do not use Invoke-Expression. It is a command injection risk. |