public IEnumerable <Match <T> > EnumerateMatches <T>(IGlobMatchableHierarchy <T> hierarchy)
        {
            var start    = new GlobMatchFactory(hierarchy.CaseSensitive).Start(glob);
            var worklist = new Worklist <Match <T> >();

            worklist.Add(new Match <T>(hierarchy.Root, start));

            while (worklist.TryTake(out var pair))
            {
                foreach (var child in hierarchy.GetChildrenMatchingPrefix(pair.Item, pair.Details.GetPrefixFilter()))
                {
                    var newState = pair.Details.MatchChild(hierarchy.GetName(child));
                    if (newState.IsMatch)
                    {
                        yield return(new Match <T>(child, newState));
                    }
                    if (newState.CanContinue && hierarchy.IsContainer(child))
                    {
                        worklist.Add(new Match <T>(child, newState));
                    }
                }
            }
        }
Beispiel #2
0
        public IEnumerable <MultiMatch <T> > EnumerateMatches <T>(IGlobMatchableHierarchy <T> hierarchy)
        {
            var factory = new GlobMatchFactory(hierarchy.CaseSensitive);

            var starts   = rules.Select(r => new Rule(factory.Start(r.Glob), r.Exclude)).ToArray();
            var worklist = new Worklist <State <T> >();

            worklist.Add(new State <T>(hierarchy.Root, starts));

            var newStates = new List <Rule>();
            var matches   = new List <GlobMatch>();

            while (worklist.TryTake(out var pair))
            {
                var includePrefix = GetCommonPrefix(pair.Current.Where(c => !c.Exclude));
                if (includePrefix == null)
                {
                    continue;                           // No inclusions remaining for this node.
                }
                foreach (var child in hierarchy.GetChildrenMatchingPrefix(pair.Item, includePrefix))
                {
                    var name        = hierarchy.GetName(child);
                    var isContainer = hierarchy.IsContainer(child);
                    var isExcluded  = false;

                    newStates.Clear();
                    matches.Clear();
                    foreach (var state in pair.Current)
                    {
                        var newState = state.Details.MatchChild(name);
                        if (state.Exclude)
                        {
                            if (newState.IsMatch)
                            {
                                isExcluded = true;
                            }
                            if (newState.MatchesAllChildren)
                            {
                                // Early exit: entire subtree is ignored for subsequent rules.
                                break;
                            }
                        }
                        else if (!isExcluded)
                        {
                            if (newState.IsMatch)
                            {
                                matches.Add(newState);
                            }
                        }

                        if (newState.CanContinue && isContainer)
                        {
                            newStates.Add(new Rule(newState, state.Exclude));
                        }
                    }
                    if (matches.Any())
                    {
                        yield return(new MultiMatch <T>(child, matches.ToArray()));
                    }
                    if (newStates.Any())
                    {
                        worklist.Add(new State <T>(child, newStates.ToArray()));
                    }
                }
            }

            string?GetCommonPrefix(IEnumerable <Rule> states)
            {
                var prefixes = states.Select(s => s.Details.GetPrefixFilter()).ToList();

                if (prefixes.Count == 0)
                {
                    return(null);
                }
                return(Util.LongestCommonPrefix(prefixes, hierarchy.CaseSensitive));
            }
        }