private static bool IsUnder(NodeQueryMatcher matcher, SearchResult result) { if (matcher.UnderProject) { var project = result.Node.GetNearestParent <Project>(); if (project != null && matcher.IsMatch(project) != null) { return(true); } var projectEvaluation = result.Node.GetNearestParent <ProjectEvaluation>(); if (projectEvaluation != null && matcher.IsMatch(projectEvaluation) != null) { return(true); } return(false); } foreach (var parent in result.Node.GetParentChainExcludingThis()) { if (matcher.IsMatch(parent) != null) { return(true); } } return(false); }
private readonly StringCache stringCache; // only used for validation that all strings are interned (disabled) public NodeQueryMatcher( string query, IEnumerable <string> stringTable, CancellationToken cancellationToken = default, StringCache stringCache = null // validation disabled in production ) { this.stringCache = stringCache; query = PreprocessQuery(query); this.Query = query; var rawWords = TextUtilities.Tokenize(query); this.Words = new List <Term>(rawWords.Count); foreach (var rawWord in rawWords) { var term = Term.Get(rawWord); if (term != default) { Words.Add(term); } } if (Words.Count == 1 && Words[0].Word is string potentialNodeIndex && potentialNodeIndex.Length > 1 && potentialNodeIndex[0] == '$') { var nodeIndexText = potentialNodeIndex.Substring(1); if (int.TryParse(nodeIndexText, out var nodeIndex)) { NodeIndex = nodeIndex; Words.RemoveAt(0); return; } } for (int i = Words.Count - 1; i >= 0; i--) { var word = Words[i].Word; if (word == "$time" || word == "$duration") { Words.RemoveAt(i); IncludeDuration = true; continue; } else if (word == "$start" || word == "$starttime") { Words.RemoveAt(i); IncludeStart = true; continue; } else if (word == "$end" || word == "$endtime") { Words.RemoveAt(i); IncludeEnd = true; continue; } if (word.Length > 2 && word[0] == '$' && word[1] != '(' && (TypeKeyword == null || !TypeKeyword.Contains(word.Substring(1).ToLowerInvariant()))) { Words.RemoveAt(i); TypeKeyword = word.Substring(1).ToLowerInvariant(); continue; } if (word.StartsWith("under(", StringComparison.OrdinalIgnoreCase) && word.EndsWith(")")) { word = word.Substring(6, word.Length - 7); Words.RemoveAt(i); var underMatcher = new NodeQueryMatcher(word, stringTable); IncludeMatchers.Add(underMatcher); continue; } if (word.StartsWith("notunder(", StringComparison.OrdinalIgnoreCase) && word.EndsWith(")")) { word = word.Substring(9, word.Length - 10); Words.RemoveAt(i); var underMatcher = new NodeQueryMatcher(word, stringTable); ExcludeMatchers.Add(underMatcher); continue; } if (word.StartsWith("project(", StringComparison.OrdinalIgnoreCase) && word.EndsWith(")")) { word = word.Substring(8, word.Length - 9); Words.RemoveAt(i); var underMatcher = new NodeQueryMatcher(word, stringTable); underMatcher.UnderProject = true; IncludeMatchers.Add(underMatcher); continue; } if (word.StartsWith("name=", StringComparison.OrdinalIgnoreCase) && word.Length > 5) { word = word.Substring(5, word.Length - 5); Words.RemoveAt(i); var term = Term.Get(word); if (term != default) { Words.Insert(i, term); nameToSearch = term; } continue; } if (word.StartsWith("value=", StringComparison.OrdinalIgnoreCase) && word.Length > 6) { word = word.Substring(6, word.Length - 6); Words.RemoveAt(i); var term = Term.Get(word); if (term != default) { Words.Insert(i, term); valueToSearch = term; } continue; } } PrecomputeMatchesInStrings(stringTable, cancellationToken); }