| File: FilterStaticWebAssetGroups.cs | Web Access |
| Project: src\sdk\src\StaticWebAssetsSdk\Tasks\Microsoft.NET.Sdk.StaticWebAssets.Tasks.csproj (Microsoft.NET.Sdk.StaticWebAssets.Tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using Microsoft.Build.Framework; namespace Microsoft.AspNetCore.StaticWebAssets.Tasks; // Unified task for filtering assets and endpoints by group declarations. // When SkipDeferred=true (first pass / pre-filter), groups marked Deferred are skipped. // When SkipDeferred=false (final pass), all groups must be concrete — an error is raised // if any group is still marked Deferred. [MSBuildMultiThreadableTask] public class FilterStaticWebAssetGroups : Task, IMultiThreadableTask { /// <inheritdoc/> public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback; [Required] public ITaskItem[] Assets { get; set; } [Required] public ITaskItem[] Endpoints { get; set; } public ITaskItem[] StaticWebAssetGroups { get; set; } // When provided, only assets with matching SourceId are filtered; others pass through. public string Source { get; set; } // When true, groups marked Deferred are skipped (first-pass pre-filter). public bool SkipDeferred { get; set; } [Output] public ITaskItem[] FilteredAssets { get; set; } // Endpoints whose asset was excluded by group filtering. [Output] public ITaskItem[] RemovedEndpoints { get; set; } // All endpoints that survived group filtering (unaffected groups + // endpoints from affected groups whose asset was not excluded). [Output] public ITaskItem[] SurvivingEndpoints { get; set; } public override bool Execute() { var groups = StaticWebAssetGroup.FromItemGroup(StaticWebAssetGroups); if (groups.Count == 0) { FilteredAssets = Assets; RemovedEndpoints = []; SurvivingEndpoints = Endpoints; return true; } if (!SkipDeferred) { foreach (var group in groups.Values) { if (group.Deferred) { Log.LogError( "Group '{0}' for source '{1}' is still marked as Deferred during final evaluation. " + "Deferred groups must be resolved before the final filtering pass.", group.Name, group.SourceId); return false; } } } var parsedAssets = StaticWebAsset.FromTaskItemGroup(Assets, TaskEnvironment); var (_, excludedAssetFiles) = StaticWebAsset.FilterByGroup(parsedAssets, groups, SkipDeferred, Source); // Null out excluded entries in-place — MSBuild ignores null ITaskItem[] entries, // so we avoid allocating a new list and re-serializing included assets. for (var i = 0; i < Assets.Length; i++) { if (excludedAssetFiles.Contains(Assets[i].ItemSpec)) { Assets[i] = null; } } FilteredAssets = Assets; var parsedEndpoints = StaticWebAssetEndpoint.FromItemGroup(Endpoints); if (excludedAssetFiles.Count > 0) { var endpointGroups = StaticWebAssetEndpointGroup.CreateEndpointGroups(parsedEndpoints); var (removedEndpoints, survivingEndpoints) = StaticWebAssetEndpointGroup.ComputeFilteredEndpoints(endpointGroups, excludedAssetFiles); foreach (var endpoint in removedEndpoints) { Log.LogMessage(MessageImportance.Low, "Excluding endpoint '{0}' because its asset file '{1}' was excluded by group filtering.", endpoint.Route, endpoint.AssetFile); } RemovedEndpoints = StaticWebAssetEndpoint.ToTaskItems(removedEndpoints); SurvivingEndpoints = StaticWebAssetEndpoint.ToTaskItems(survivingEndpoints); } else { RemovedEndpoints = []; SurvivingEndpoints = StaticWebAssetEndpoint.ToTaskItems(parsedEndpoints); } return !Log.HasLoggedErrors; } }