@@ -37,11 +37,13 @@ public class UseShouldProcessCorrectly : IScriptRule
3737 private FunctionReferenceDigraph funcDigraph ;
3838 private List < DiagnosticRecord > diagnosticRecords ;
3939 private readonly Vertex shouldProcessVertex ;
40+ private readonly Vertex implicitShouldProcessVertex ;
4041
4142 public UseShouldProcessCorrectly ( )
4243 {
4344 diagnosticRecords = new List < DiagnosticRecord > ( ) ;
4445 shouldProcessVertex = new Vertex ( "ShouldProcess" , null ) ;
46+ implicitShouldProcessVertex = new Vertex ( "implicitShouldProcessVertex" , null ) ;
4547 }
4648
4749 /// <summary>
@@ -150,10 +152,12 @@ private DiagnosticRecord GetViolation(Vertex v)
150152 return null ;
151153 }
152154
153- bool callsShouldProcess = funcDigraph . IsConnected ( v , shouldProcessVertex ) ;
154155 if ( DeclaresSupportsShouldProcess ( fast ) )
155156 {
156- if ( ! callsShouldProcess )
157+ bool callsShouldProcess = funcDigraph . IsConnected ( v , shouldProcessVertex ) ;
158+ bool callsCommandWithShouldProcess = funcDigraph . IsConnected ( v , implicitShouldProcessVertex ) ;
159+ if ( ! callsShouldProcess
160+ && ! callsCommandWithShouldProcess )
157161 {
158162 return new DiagnosticRecord (
159163 string . Format (
@@ -168,12 +172,12 @@ private DiagnosticRecord GetViolation(Vertex v)
168172 }
169173 else
170174 {
171- if ( callsShouldProcess )
175+ if ( callsShouldProcessDirectly ( v ) )
172176 {
173177 // check if upstream function declares SupportShouldProcess
174178 // if so, this might just be a helper function
175179 // do not flag this case
176- if ( UpstreamDeclaresShouldProcess ( v ) )
180+ if ( v . IsNestedFunctionDefinition && UpstreamDeclaresShouldProcess ( v ) )
177181 {
178182 return null ;
179183 }
@@ -193,6 +197,11 @@ private DiagnosticRecord GetViolation(Vertex v)
193197 return null ;
194198 }
195199
200+ private bool callsShouldProcessDirectly ( Vertex vertex )
201+ {
202+ return funcDigraph . GetNeighbors ( vertex ) . Contains ( shouldProcessVertex ) ;
203+ }
204+
196205 /// <summary>
197206 /// Checks if an upstream function declares SupportsShouldProcess
198207 /// </summary>
@@ -344,10 +353,10 @@ private void CheckForSupportShouldProcess()
344353
345354 if ( commandsWithSupportShouldProcess . Count > 0 )
346355 {
347- funcDigraph . AddVertex ( shouldProcessVertex ) ;
356+ funcDigraph . AddVertex ( implicitShouldProcessVertex ) ;
348357 foreach ( var v in commandsWithSupportShouldProcess )
349358 {
350- funcDigraph . AddEdge ( v , shouldProcessVertex ) ;
359+ funcDigraph . AddEdge ( v , implicitShouldProcessVertex ) ;
351360 }
352361 }
353362 }
@@ -359,10 +368,23 @@ private void CheckForSupportShouldProcess()
359368 class Vertex
360369 {
361370 public string Name { get { return name ; } }
362- public Ast Ast { get { return ast ; } }
371+ public Ast Ast
372+ {
373+ get
374+ {
375+ return ast ;
376+ }
377+ set
378+ {
379+ ast = value ;
380+ }
381+ }
382+
383+ public bool IsNestedFunctionDefinition { get { return isNestedFunctionDefinition ; } }
363384
364385 private string name ;
365386 private Ast ast ;
387+ private bool isNestedFunctionDefinition ;
366388
367389 public Vertex ( )
368390 {
@@ -379,6 +401,12 @@ public Vertex (string name, Ast ast)
379401 this . ast = ast ;
380402 }
381403
404+ public Vertex ( String name , Ast ast , bool isNestedFunctionDefinition )
405+ : this ( name , ast )
406+ {
407+ this . isNestedFunctionDefinition = isNestedFunctionDefinition ;
408+ }
409+
382410 /// <summary>
383411 /// Returns string representation of a Vertex instance
384412 /// </summary>
@@ -460,11 +488,30 @@ public FunctionReferenceDigraph()
460488 /// <summary>
461489 /// Add a vertex to the graph
462490 /// </summary>
463- public void AddVertex ( Vertex name )
491+ public void AddVertex ( Vertex vertex )
464492 {
465- if ( ! digraph . ContainsVertex ( name ) )
493+ bool containsVertex = false ;
494+
495+ // if the graph contains a vertex with name equal to that
496+ // of the input vertex, then update the vertex's ast if the
497+ // input vertex's ast is of FunctionDefinitionAst type
498+ foreach ( Vertex v in digraph . GetVertices ( ) )
499+ {
500+ if ( v . Equals ( vertex ) )
501+ {
502+ containsVertex = true ;
503+ if ( vertex . Ast != null
504+ && vertex . Ast is FunctionDefinitionAst )
505+ {
506+ v . Ast = vertex . Ast ;
507+ }
508+ break ;
509+ }
510+ }
511+
512+ if ( ! containsVertex )
466513 {
467- digraph . AddVertex ( name ) ;
514+ digraph . AddVertex ( vertex ) ;
468515 }
469516 }
470517
@@ -491,7 +538,7 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast
491538 return AstVisitAction . SkipChildren ;
492539 }
493540
494- var functionVertex = new Vertex ( ast . Name , ast ) ;
541+ var functionVertex = new Vertex ( ast . Name , ast , IsWithinFunctionDefinition ( ) ) ;
495542 functionVisitStack . Push ( functionVertex ) ;
496543 AddVertex ( functionVertex ) ;
497544 ast . Body . Visit ( this ) ;
@@ -549,18 +596,15 @@ public override AstVisitAction VisitInvokeMemberExpression(InvokeMemberExpressio
549596 }
550597
551598 // Suppose we find <Expression>.<Member>, we split it up and create
552- // and edge from <Expression>-> <Member>. Even though <Expression> is not
599+ // and edge only to <Member>. Even though <Expression> is not
553600 // necessarily a function, we do it because we are mainly interested in
554601 // finding connection between a function and ShouldProcess and this approach
555602 // prevents any unnecessary complexity.
556- var exprVertex = new Vertex ( expr , ast . Expression ) ;
557603 var memberVertex = new Vertex ( memberExprAst . Value , memberExprAst ) ;
558- AddVertex ( exprVertex ) ;
559604 AddVertex ( memberVertex ) ;
560- AddEdge ( exprVertex , memberVertex ) ;
561605 if ( IsWithinFunctionDefinition ( ) )
562606 {
563- AddEdge ( GetCurrentFunctionContext ( ) , exprVertex ) ;
607+ AddEdge ( GetCurrentFunctionContext ( ) , memberVertex ) ;
564608 }
565609
566610 return AstVisitAction . Continue ;
@@ -597,5 +641,10 @@ public int GetOutDegree(Vertex v)
597641 {
598642 return digraph . GetOutDegree ( v ) ;
599643 }
644+
645+ public IEnumerable < Vertex > GetNeighbors ( Vertex v )
646+ {
647+ return digraph . GetNeighbors ( v ) ;
648+ }
600649 }
601650}
0 commit comments