@@ -36,6 +36,12 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
3636
3737 foreach ( ScriptBlockAst scriptBlockAst in scriptBlockAsts )
3838 {
39+ // bail out if PS bound parameter used.
40+ if ( scriptBlockAst . Find ( IsBoundParametersReference , searchNestedScriptBlocks : false ) != null )
41+ {
42+ continue ;
43+ }
44+
3945 // find all declared parameters
4046 IEnumerable < Ast > parameterAsts = scriptBlockAst . FindAll ( oneAst => oneAst is ParameterAst , false ) ;
4147
@@ -45,12 +51,6 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4551 . GroupBy ( variableName => variableName , StringComparer . OrdinalIgnoreCase )
4652 . ToDictionary ( variableName => variableName . Key , variableName => variableName . Count ( ) , StringComparer . OrdinalIgnoreCase ) ;
4753
48- // all bets are off if the script uses PSBoundParameters
49- if ( variableCount . ContainsKey ( "PSBoundParameters" ) )
50- {
51- continue ;
52- }
53-
5454 foreach ( ParameterAst parameterAst in parameterAsts )
5555 {
5656 // there should be at least two usages of the variable since the parameter declaration counts as one
@@ -72,6 +72,47 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
7272 }
7373 }
7474
75+ /// <summary>
76+ /// Checks for PS bound parameter reference.
77+ /// </summary>
78+ /// <param name="ast">AST to be analyzed. This should be non-null</param>
79+ /// <returns>Boolean true indicating that given AST has PS bound parameter reference, otherwise false</returns>
80+ private static bool IsBoundParametersReference ( Ast ast )
81+ {
82+ // $PSBoundParameters
83+ if ( ast is VariableExpressionAst variableAst
84+ && variableAst . VariablePath . UserPath . Equals ( "PSBoundParameters" , StringComparison . OrdinalIgnoreCase ) )
85+ {
86+ return true ;
87+ }
88+
89+ if ( ast is MemberExpressionAst memberAst
90+ && memberAst . Member is StringConstantExpressionAst memberStringAst
91+ && memberStringAst . Value . Equals ( "BoundParameters" , StringComparison . OrdinalIgnoreCase ) )
92+ {
93+ // $MyInvocation.BoundParameters
94+ if ( memberAst . Expression is VariableExpressionAst veAst
95+ && veAst . VariablePath . UserPath . Equals ( "MyInvocation" , StringComparison . OrdinalIgnoreCase ) )
96+ {
97+ return true ;
98+ }
99+
100+ // $PSCmdlet.MyInvocation.BoundParameters
101+ if ( memberAst . Expression is MemberExpressionAst meAstNested )
102+ {
103+ if ( meAstNested . Expression is VariableExpressionAst veAstNested
104+ && veAstNested . VariablePath . UserPath . Equals ( "PSCmdlet" , StringComparison . OrdinalIgnoreCase )
105+ && meAstNested . Member is StringConstantExpressionAst sceAstNested
106+ && sceAstNested . Value . Equals ( "MyInvocation" , StringComparison . OrdinalIgnoreCase ) )
107+ {
108+ return true ;
109+ }
110+ }
111+ }
112+
113+ return false ;
114+ }
115+
75116 /// <summary>
76117 /// GetName: Retrieves the name of this rule.
77118 /// </summary>
0 commit comments