66using System . Linq ;
77using Microsoft . Extensions . FileSystemGlobbing . Abstractions ;
88using Microsoft . Extensions . FileSystemGlobbing . Internal . PathSegments ;
9+ using Microsoft . Extensions . FileSystemGlobbing . Internal . PatternContexts ;
910using Microsoft . Extensions . FileSystemGlobbing . Util ;
1011
1112namespace Microsoft . Extensions . FileSystemGlobbing . Internal
@@ -17,8 +18,7 @@ namespace Microsoft.Extensions.FileSystemGlobbing.Internal
1718 public class MatcherContext
1819 {
1920 private readonly DirectoryInfoBase _root ;
20- private readonly IPatternContext [ ] _includePatternContexts ;
21- private readonly IPatternContext [ ] _excludePatternContexts ;
21+ private readonly IPatternContext _patternContext ;
2222 private readonly List < FilePatternMatch > _files ;
2323
2424 private readonly HashSet < string > _declaredLiteralFolderSegmentInString ;
@@ -27,22 +27,33 @@ public class MatcherContext
2727 private bool _declaredParentPathSegment ;
2828 private bool _declaredWildcardPathSegment ;
2929
30- private readonly StringComparison _comparisonType ;
31-
32- public MatcherContext (
33- IEnumerable < IPattern > includePatterns ,
34- IEnumerable < IPattern > excludePatterns ,
35- DirectoryInfoBase directoryInfo ,
36- StringComparison comparison )
30+ public MatcherContext ( IEnumerable < IPattern > includePatterns , IEnumerable < IPattern > excludePatterns , DirectoryInfoBase directoryInfo , StringComparison comparison )
3731 {
3832 _root = directoryInfo ;
39- _files = new List < FilePatternMatch > ( ) ;
40- _comparisonType = comparison ;
33+ _files = [ ] ;
34+ _declaredLiteralFolderSegmentInString = new HashSet < string > ( StringComparisonHelper . GetStringComparer ( comparison ) ) ;
4135
42- _includePatternContexts = includePatterns . Select ( pattern => pattern . CreatePatternContextForInclude ( ) ) . ToArray ( ) ;
43- _excludePatternContexts = excludePatterns . Select ( pattern => pattern . CreatePatternContextForExclude ( ) ) . ToArray ( ) ;
36+ IPatternContext [ ] includePatternContexts = includePatterns . Select ( pattern => pattern . CreatePatternContextForInclude ( ) ) . ToArray ( ) ;
37+ IPatternContext [ ] excludePatternContexts = excludePatterns . Select ( pattern => pattern . CreatePatternContextForExclude ( ) ) . ToArray ( ) ;
38+
39+ _patternContext = new IncludesFirstCompositePatternContext ( includePatternContexts , excludePatternContexts ) ;
40+ }
4441
42+ internal MatcherContext ( List < IncludeOrExcludeValue < IPattern > > orderedPatterns , DirectoryInfoBase directoryInfo , StringComparison comparison )
43+ {
44+ _root = directoryInfo ;
45+ _files = [ ] ;
4546 _declaredLiteralFolderSegmentInString = new HashSet < string > ( StringComparisonHelper . GetStringComparer ( comparison ) ) ;
47+
48+ IncludeOrExcludeValue < IPatternContext > [ ] includeOrExcludePatternContexts = orderedPatterns
49+ . Select ( item => new IncludeOrExcludeValue < IPatternContext >
50+ {
51+ Value = item . IsInclude ? item . Value . CreatePatternContextForInclude ( ) : item . Value . CreatePatternContextForExclude ( ) ,
52+ IsInclude = item . IsInclude
53+ } )
54+ . ToArray ( ) ;
55+
56+ _patternContext = new PreserveOrderCompositePatternContext ( includeOrExcludePatternContexts ) ;
4657 }
4758
4859 public PatternMatchingResult Execute ( )
@@ -57,7 +68,7 @@ public PatternMatchingResult Execute()
5768 private void Match ( DirectoryInfoBase directory , string ? parentRelativePath )
5869 {
5970 // Request all the including and excluding patterns to push current directory onto their status stack.
60- PushDirectory ( directory ) ;
71+ _patternContext . PushDirectory ( directory ) ;
6172 Declare ( ) ;
6273
6374 var entities = new List < FileSystemInfoBase ? > ( ) ;
@@ -89,7 +100,7 @@ private void Match(DirectoryInfoBase directory, string? parentRelativePath)
89100 {
90101 if ( entity is FileInfoBase fileInfo )
91102 {
92- PatternTestResult result = MatchPatternContexts ( fileInfo , ( pattern , file ) => pattern . Test ( file ) ) ;
103+ PatternTestResult result = _patternContext . Test ( fileInfo ) ;
93104 if ( result . IsSuccessful )
94105 {
95106 _files . Add ( new FilePatternMatch (
@@ -102,7 +113,7 @@ private void Match(DirectoryInfoBase directory, string? parentRelativePath)
102113
103114 if ( entity is DirectoryInfoBase directoryInfo )
104115 {
105- if ( MatchPatternContexts ( directoryInfo , ( pattern , dir ) => pattern . Test ( dir ) ) )
116+ if ( _patternContext . Test ( directoryInfo ) )
106117 {
107118 subDirectories . Add ( directoryInfo ) ;
108119 }
@@ -120,7 +131,7 @@ private void Match(DirectoryInfoBase directory, string? parentRelativePath)
120131 }
121132
122133 // Request all the including and excluding patterns to pop their status stack.
123- PopDirectory ( ) ;
134+ _patternContext . PopDirectory ( ) ;
124135 }
125136
126137 private void Declare ( )
@@ -129,10 +140,7 @@ private void Declare()
129140 _declaredParentPathSegment = false ;
130141 _declaredWildcardPathSegment = false ;
131142
132- foreach ( IPatternContext include in _includePatternContexts )
133- {
134- include . Declare ( DeclareInclude ) ;
135- }
143+ _patternContext . Declare ( DeclareInclude ) ;
136144 }
137145
138146 private void DeclareInclude ( IPathSegment patternSegment , bool isLastSegment )
@@ -169,82 +177,5 @@ internal static string CombinePath(string? left, string right)
169177 return $ "{ left } /{ right } ";
170178 }
171179 }
172-
173- // Used to adapt Test(DirectoryInfoBase) for the below overload
174- private bool MatchPatternContexts < TFileInfoBase > ( TFileInfoBase fileinfo , Func < IPatternContext , TFileInfoBase , bool > test )
175- {
176- return MatchPatternContexts (
177- fileinfo ,
178- ( ctx , file ) =>
179- {
180- if ( test ( ctx , file ) )
181- {
182- return PatternTestResult . Success ( stem : string . Empty ) ;
183- }
184- else
185- {
186- return PatternTestResult . Failed ;
187- }
188- } ) . IsSuccessful ;
189- }
190-
191- private PatternTestResult MatchPatternContexts < TFileInfoBase > ( TFileInfoBase fileinfo , Func < IPatternContext , TFileInfoBase , PatternTestResult > test )
192- {
193- PatternTestResult result = PatternTestResult . Failed ;
194-
195- // If the given file/directory matches any including pattern, continues to next step.
196- foreach ( IPatternContext context in _includePatternContexts )
197- {
198- PatternTestResult localResult = test ( context , fileinfo ) ;
199- if ( localResult . IsSuccessful )
200- {
201- result = localResult ;
202- break ;
203- }
204- }
205-
206- // If the given file/directory doesn't match any of the including pattern, returns false.
207- if ( ! result . IsSuccessful )
208- {
209- return PatternTestResult . Failed ;
210- }
211-
212- // If the given file/directory matches any excluding pattern, returns false.
213- foreach ( IPatternContext context in _excludePatternContexts )
214- {
215- if ( test ( context , fileinfo ) . IsSuccessful )
216- {
217- return PatternTestResult . Failed ;
218- }
219- }
220-
221- return result ;
222- }
223-
224- private void PopDirectory ( )
225- {
226- foreach ( IPatternContext context in _excludePatternContexts )
227- {
228- context . PopDirectory ( ) ;
229- }
230-
231- foreach ( IPatternContext context in _includePatternContexts )
232- {
233- context . PopDirectory ( ) ;
234- }
235- }
236-
237- private void PushDirectory ( DirectoryInfoBase directory )
238- {
239- foreach ( IPatternContext context in _includePatternContexts )
240- {
241- context . PushDirectory ( directory ) ;
242- }
243-
244- foreach ( IPatternContext context in _excludePatternContexts )
245- {
246- context . PushDirectory ( directory ) ;
247- }
248- }
249180 }
250181}
0 commit comments