in src/StructuredLogger/Search/PropertiesAndItemsSearch.cs [11:127]
public IEnumerable<SearchResult> Search(
TimedNode context,
string searchText,
int maxResults,
bool markResultsInTree,
CancellationToken cancellationToken)
{
var roots = new List<TreeNode>();
Build build = context.GetRoot() as Build;
Project project = context as Project;
if (project != null && build != null)
{
var projectEvaluation = build.FindEvaluation(project.EvaluationId);
if (projectEvaluation != null)
{
AddPropertiesAndItems(projectEvaluation, roots);
}
}
AddPropertiesAndItems(context, roots);
static void AddPropertiesAndItems(TimedNode root, List<TreeNode> roots)
{
Folder properties = root.FindChild<Folder>(Strings.Properties);
if (properties != null)
{
roots.Add(properties);
}
Folder items = root.FindChild<Folder>(Strings.Items);
if (items != null)
{
roots.Add(items);
}
var reassignments = root.FindChild<TimedNode>(Strings.PropertyReassignmentFolder);
if (reassignments != null)
{
roots.Add(reassignments);
}
}
var strings = new StringCache();
foreach (var root in roots)
{
CollectStrings(root, strings);
}
var search = new Search(roots, strings.Instances, maxResults, markResultsInTree);
var results = search.FindNodes(searchText, cancellationToken);
// When they're searching for $additem Foo, add the contents of the $additem folder
// to search results, because this is what they likely want
var otherResults = new List<SearchResult>();
// Find all folders where no other results are under that folder.
// First find all ancestors of all non-folders.
var allAncestors = new HashSet<BaseNode>();
foreach (var result in results)
{
var node = result.Node;
if (node is not Folder itemType)
{
otherResults.Add(result);
foreach (var ancestor in node.GetParentChainExcludingThis())
{
allAncestors.Add(ancestor);
}
}
}
var includeFolderChildren = new List<BaseNode>();
// Iterate over all folders where no other results are under that folder.
foreach (var folder in results.Select(r => r.Node).OfType<Folder>().Where(f => !allAncestors.Contains(f)))
{
foreach (var item in folder.Children.OfType<Item>())
{
includeFolderChildren.Add(item);
}
}
results =
otherResults
.Concat(includeFolderChildren.Select(c =>
{
var result = new SearchResult(c);
return result;
}))
.ToArray();
var nodesSoFar = new HashSet<BaseNode>(results.Select(r => r.Node));
// Now add results from execution (not evaluation) under current project
if (project != null && build != null)
{
var executionSearchText = $"{searchText} project(${project.Index})";
var executionSearch = new Search(
project.Children.OfType<Target>(),
build.StringTable.Instances,
maxResults,
markResultsInTree);
var executionResults = executionSearch.FindNodes(executionSearchText, cancellationToken);
executionResults = executionResults.Where(r =>
(r.Node is Property ||
r.Node is Item ||
r.Node is AddItem ||
r.Node is RemoveItem)
&& !nodesSoFar.Contains(r.Node));
results = results.Concat(executionResults).ToArray();
}
return results;
}