@@ -799,6 +799,8 @@ internal sealed class PwshForEachValueAnalyzer
799799 new ( ClauseReferenceComparer . Instance ) ;
800800 private bool _isComplete = true ;
801801 private int _remainingLoopAnalysisTransitions = MaxLoopAnalysisTransitions ;
802+ private long _executionRegionEffectCount ;
803+ private long _nonRegionStateMutationCount ;
802804
803805 private PwshForEachValueAnalyzer (
804806 PwshParserOptions options ,
@@ -861,9 +863,15 @@ private PwshFlowResult AnalyzeNode(ShellSyntaxNode node, AnalysisContext input)
861863 GroupSyntax group => AnalyzeGroup ( group , input ) ,
862864 ForEachSyntax forEach => AnalyzeForEach ( forEach , input ) ,
863865 CommandSubstitutionSyntax substitution => AnalyzeSubstitution ( substitution , input ) ,
864- _ => PwshFlowResult . Both ( input . Invalidate ( unknownCwd : true ) ) ,
866+ _ => AnalyzeUnsupportedNode ( input ) ,
865867 } ;
866868
869+ private PwshFlowResult AnalyzeUnsupportedNode ( AnalysisContext input )
870+ {
871+ _nonRegionStateMutationCount ++ ;
872+ return PwshFlowResult . Both ( input . Invalidate ( unknownCwd : true ) ) ;
873+ }
874+
867875 private PwshFlowResult AnalyzeBlock ( ShellBlockSyntax block , AnalysisContext input )
868876 {
869877 var flow = PwshFlowResult . Both ( input ) ;
@@ -899,7 +907,8 @@ private PwshFlowResult AnalyzeSimple(SimpleCommandSyntax simple, AnalysisContext
899907 var effective = CreateEffectiveArguments (
900908 source . ValueProvenance ,
901909 current ,
902- includeUnresolved : isForEachIncomplete ) ;
910+ includeUnresolved : isForEachIncomplete ||
911+ current . CommandResolutionInvalidated ) ;
903912 var mayPromote = current . CanPromote &&
904913 source . HasCompleteValueProvenance &&
905914 simple . Substitutions . Count == 0 &&
@@ -916,38 +925,64 @@ private PwshFlowResult AnalyzeSimple(SimpleCommandSyntax simple, AnalysisContext
916925 var location = AnalyzeSetLocation ( simple , current ) ;
917926 if ( location is not null )
918927 {
928+ _nonRegionStateMutationCount ++ ;
919929 if ( PwshPersistentStateMutation . TryGetEffect (
920930 simple . Clause ,
921931 effective ,
922932 out var locationEffectUnknownCwd ) )
923933 {
924934 var flow = location . Value ;
925- return new PwshFlowResult (
935+ return ApplyExecutionRegionEffect ( simple , new PwshFlowResult (
926936 flow . OnSuccess is AnalysisContext success
927937 ? success . Invalidate ( locationEffectUnknownCwd )
928938 : null ,
929939 flow . OnFailure is AnalysisContext failure
930940 ? failure . Invalidate ( locationEffectUnknownCwd )
931- : null ) ;
941+ : null ) ) ;
932942 }
933943
934- return location . Value ;
944+ return ApplyExecutionRegionEffect ( simple , location . Value ) ;
935945 }
936946
937947 if ( simple . Clause . Verb . IsDynamic )
938948 {
939- return PwshFlowResult . Both ( current . Invalidate ( unknownCwd : true ) ) ;
949+ _nonRegionStateMutationCount ++ ;
950+ return ApplyExecutionRegionEffect (
951+ simple ,
952+ PwshFlowResult . Both ( current . Invalidate ( unknownCwd : true ) ) ) ;
940953 }
941954
942955 if ( PwshPersistentStateMutation . TryGetEffect (
943956 simple . Clause ,
944957 effective ,
945958 out var unknownCwd ) )
946959 {
947- return PwshFlowResult . Both ( current . Invalidate ( unknownCwd ) ) ;
960+ _nonRegionStateMutationCount ++ ;
961+ return ApplyExecutionRegionEffect (
962+ simple ,
963+ PwshFlowResult . Both ( current . Invalidate ( unknownCwd ) ) ) ;
964+ }
965+
966+ return ApplyExecutionRegionEffect ( simple , PwshFlowResult . Both ( current ) ) ;
967+ }
968+
969+ private PwshFlowResult ApplyExecutionRegionEffect (
970+ SimpleCommandSyntax simple ,
971+ PwshFlowResult flow )
972+ {
973+ if ( simple . ExecutionRegions . Count == 0 )
974+ {
975+ return flow ;
948976 }
949977
950- return PwshFlowResult . Both ( current ) ;
978+ _executionRegionEffectCount ++ ;
979+ return new PwshFlowResult (
980+ flow . OnSuccess is AnalysisContext success
981+ ? success . Invalidate ( unknownCwd : true )
982+ : null ,
983+ flow . OnFailure is AnalysisContext failure
984+ ? failure . Invalidate ( unknownCwd : true )
985+ : null ) ;
951986 }
952987
953988 private void RecordFacts (
@@ -1044,22 +1079,34 @@ private PwshFlowResult AnalyzeList(CommandListSyntax list, AnalysisContext input
10441079
10451080 private PwshFlowResult AnalyzePipeline ( PipelineSyntax pipeline , AnalysisContext input )
10461081 {
1082+ var stageInput = input ;
10471083 foreach ( var stage in pipeline . Stages )
10481084 {
1049- var stageFlow = AnalyzeNode ( stage , input ) ;
1085+ var executionRegionEffectsBefore = _executionRegionEffectCount ;
1086+ var nonRegionMutationsBefore = _nonRegionStateMutationCount ;
1087+ var stageFlow = AnalyzeNode ( stage , stageInput ) ;
10501088 if ( stageFlow . JoinedState is not AnalysisContext stageExit )
10511089 {
10521090 return new PwshFlowResult ( null , null ) ;
10531091 }
10541092
1055- if ( ! input . StateEquals ( stageExit ) )
1093+ if ( ! stageInput . StateEquals ( stageExit ) )
10561094 {
1057- _isComplete = false ;
1058- return new PwshFlowResult ( null , null ) ;
1095+ var regionCausedTransition =
1096+ _executionRegionEffectCount > executionRegionEffectsBefore ;
1097+ var unrelatedMutationCausedTransition =
1098+ _nonRegionStateMutationCount > nonRegionMutationsBefore ;
1099+ if ( ! regionCausedTransition || unrelatedMutationCausedTransition )
1100+ {
1101+ _isComplete = false ;
1102+ return new PwshFlowResult ( null , null ) ;
1103+ }
1104+
1105+ stageInput = stageInput . Invalidate ( unknownCwd : true ) ;
10591106 }
10601107 }
10611108
1062- return PwshFlowResult . Both ( input ) ;
1109+ return PwshFlowResult . Both ( stageInput ) ;
10631110 }
10641111
10651112 private PwshFlowResult AnalyzeGroup ( GroupSyntax group , AnalysisContext input )
@@ -1069,11 +1116,15 @@ private PwshFlowResult AnalyzeGroup(GroupSyntax group, AnalysisContext input)
10691116 return AnalyzeBlock ( group . Body , input ) ;
10701117 }
10711118
1119+ var executionRegionEffectCount = _executionRegionEffectCount ;
1120+ var nonRegionStateMutationCount = _nonRegionStateMutationCount ;
10721121 AnalyzeBlock (
10731122 group . Body ,
10741123 input . WithoutBindings ( ) . Invalidate (
10751124 unknownCwd : false ,
10761125 invalidateCommandResolution : false ) ) ;
1126+ _executionRegionEffectCount = executionRegionEffectCount ;
1127+ _nonRegionStateMutationCount = nonRegionStateMutationCount ;
10771128 return PwshFlowResult . Both ( input ) ;
10781129 }
10791130
@@ -1086,6 +1137,7 @@ private PwshFlowResult AnalyzeSubstitution(
10861137
10871138 private PwshFlowResult AnalyzeForEach ( ForEachSyntax forEach , AnalysisContext input )
10881139 {
1140+ _nonRegionStateMutationCount ++ ;
10891141 var plan = _planFactory ( forEach ) ;
10901142 if ( plan is null )
10911143 {
@@ -1446,6 +1498,16 @@ private SimpleCommandSyntax RewriteSimple(
14461498 facts ) ;
14471499 }
14481500
1501+ var executionRegions = new ExecutionRegionSyntax [ simple . ExecutionRegions . Count ] ;
1502+ for ( var index = 0 ; index < executionRegions . Length ; index ++ )
1503+ {
1504+ var region = simple . ExecutionRegions [ index ] ;
1505+ executionRegions [ index ] = region with
1506+ {
1507+ Body = RewriteBlock ( region . Body , facts ) ,
1508+ } ;
1509+ }
1510+
14491511 var source = GetFacts ( simple ) ;
14501512 var clause = RewriteCwdCompatibility (
14511513 simple . Clause ,
@@ -1465,6 +1527,7 @@ private SimpleCommandSyntax RewriteSimple(
14651527 {
14661528 Clause = clause ,
14671529 Substitutions = substitutions ,
1530+ ExecutionRegions = executionRegions ,
14681531 } ;
14691532 }
14701533
0 commit comments