diff --git a/Engine/Helper.cs b/Engine/Helper.cs
index 70bd69f6b..41c0a326a 100644
--- a/Engine/Helper.cs
+++ b/Engine/Helper.cs
@@ -700,7 +700,8 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst)
VariableAnalysis previousOuter = OuterAnalysis;
- // We already run variable analysis in these cases so check
+ // We already run variable analysis if the parent is a function so skip these.
+ // Otherwise, we have to do variable analysis using the outer scope variables.
if (!(scriptBlockAst.Parent is FunctionDefinitionAst) && !(scriptBlockAst.Parent is FunctionMemberAst))
{
OuterAnalysis = Helper.Instance.InitializeVariableAnalysisHelper(scriptBlockAst, OuterAnalysis);
@@ -726,8 +727,15 @@ public object VisitScriptBlock(ScriptBlockAst scriptBlockAst)
scriptBlockAst.EndBlock.Visit(this);
}
+ VariableAnalysis innerAnalysis = OuterAnalysis;
OuterAnalysis = previousOuter;
+ if (!(scriptBlockAst.Parent is FunctionDefinitionAst) && !(scriptBlockAst.Parent is FunctionMemberAst))
+ {
+ // Update the variable analysis of the outer script block
+ VariableAnalysis.UpdateOuterAnalysis(OuterAnalysis, innerAnalysis);
+ }
+
return null;
}
@@ -889,6 +897,13 @@ public object VisitCatchClause(CatchClauseAst catchClauseAst)
///
public object VisitCommand(CommandAst commandAst)
{
+ if (commandAst == null) return null;
+
+ foreach (CommandElementAst ceAst in commandAst.CommandElements)
+ {
+ ceAst.Visit(this);
+ }
+
return null;
}
@@ -1219,12 +1234,19 @@ public object VisitParenExpression(ParenExpressionAst parenExpressionAst)
}
///
- /// Do nothing
+ /// Visit pipeline
///
///
///
public object VisitPipeline(PipelineAst pipelineAst)
{
+ if (pipelineAst == null) return null;
+
+ foreach (var command in pipelineAst.PipelineElements)
+ {
+ command.Visit(this);
+ }
+
return null;
}
diff --git a/Engine/VariableAnalysis.cs b/Engine/VariableAnalysis.cs
index bbfa309cf..352ab40ef 100644
--- a/Engine/VariableAnalysis.cs
+++ b/Engine/VariableAnalysis.cs
@@ -255,6 +255,31 @@ public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis)
}
}
+ ///
+ /// Updates the variablesdictionary of the outeranalysis based on that of the inneranalysis
+ ///
+ ///
+ ///
+ internal static void UpdateOuterAnalysis(VariableAnalysis OuterAnalysis, VariableAnalysis InnerAnalysis)
+ {
+ if (OuterAnalysis == null || InnerAnalysis == null)
+ {
+ return;
+ }
+
+ foreach (var key in InnerAnalysis.VariablesDictionary.Keys)
+ {
+ if (OuterAnalysis.VariablesDictionary.ContainsKey(key))
+ {
+ OuterAnalysis.VariablesDictionary[key] = InnerAnalysis.VariablesDictionary[key];
+ }
+ else
+ {
+ OuterAnalysis.VariablesDictionary.Add(key, InnerAnalysis.VariablesDictionary[key]);
+ }
+ }
+ }
+
///
/// Return variableanalysisdetails for VarTarget.
/// This function should only be called after Block.SparseSimpleConstants are called.
diff --git a/Engine/VariableAnalysisBase.cs b/Engine/VariableAnalysisBase.cs
index 5f136b99b..17e7cc6c8 100644
--- a/Engine/VariableAnalysisBase.cs
+++ b/Engine/VariableAnalysisBase.cs
@@ -2957,10 +2957,6 @@ public object VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExp
{
// Don't recurse into the script block, it's variables are distinct from the script block
// we're currently analyzing.
- if (scriptBlockExpressionAst != null)
- {
- scriptBlockExpressionAst.ScriptBlock.Visit(this.Decorator);
- }
return null;
}
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
index e9979a297..ef6988ad9 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVars.ps1
@@ -19,4 +19,7 @@ while ($false) {
$a;
# $d may not be initialized too
-$d;
\ No newline at end of file
+$d;
+
+# error must be raised here
+Invoke-Command -ScriptBlock {$a; }
\ No newline at end of file
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
index 537f57024..bad960927 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVars.tests.ps1
@@ -31,8 +31,8 @@ Describe "AvoidGlobalVars" {
Describe "AvoidUnitializedVars" {
Context "When there are violations" {
- It "has 4 avoid using unitialized variable violations" {
- $nonInitializedViolations.Count | Should Be 4
+ It "has 5 avoid using unitialized variable violations" {
+ $nonInitializedViolations.Count | Should Be 5
}
It "has the correct description message" {
diff --git a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1 b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
index ca914bce5..b5206cd68 100644
--- a/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
+++ b/Tests/Rules/AvoidGlobalOrUnitializedVarsNoViolations.ps1
@@ -22,6 +22,8 @@ stop-process 12,23 -ErrorVariable ev -ErrorAction SilentlyContinue
if($null -ne $ev)
{
Write-host $ev[0]
+ # no error should be raised here
+ Invoke-Command {$b}
}
get-process notepad | tee-object -variable proc