Skip to content

Address follow-up review feedback for matcher reuse and null-pattern validation#1770

Merged
jpinz merged 14 commits intomainfrom
fix/glob-pattern-matching
Apr 10, 2026
Merged

Address follow-up review feedback for matcher reuse and null-pattern validation#1770
jpinz merged 14 commits intomainfrom
fix/glob-pattern-matching

Conversation

@jpinz
Copy link
Copy Markdown
Member

@jpinz jpinz commented Apr 7, 2026

This pull request refactors and modernizes the file pattern matching logic throughout the codebase. The main improvements are the introduction of a new PatternMatchingUtility.CompiledMatcher class for efficient, reusable pattern matching, the removal of legacy pattern matching code, and the simplification of APIs that deal with file pattern matching. These changes improve maintainability, performance, and code clarity.

Worth noting is that as a part of this change, the ordering of the SearchPatterns in each detector is now ordered so that earlier patterns have a higher priority when multiple patterns match a file.

Additionally, only one ProcessRequest is returned per matching file, previously we returned one per matching pattern.

Old behavior (one per matching pattern): If a file like package.json matched both *.json and package.json, the detector's OnFileFoundAsync would be called twice for the same file. Both calls would parse the same content and register the same components into the same SingleFileComponentRecorder (since it's keyed by file path via CreateSingleFileComponentRecorder(lazyComponentStream.Location)). The second call is pure waste.

New behavior (one per file): Each file is processed exactly once. No duplicate parsing, no redundant RegisterUsage calls.

…ob patterns efficiently. And align on one implementation of pattern/file matching.
@jpinz jpinz requested a review from JamieMagee April 7, 2026 21:13
@jpinz jpinz self-assigned this Apr 7, 2026
Copilot AI review requested due to automatic review settings April 7, 2026 21:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates file name pattern matching to a centralized implementation (PatternMatchingUtility), removing legacy matching logic from PathUtilityService and updating the directory/file enumeration code paths and tests to use the new matcher.

Changes:

  • Introduced span-based pattern matching using System.IO.Enumeration.FileSystemName.MatchesSimpleExpression and a reusable CompiledMatcher.
  • Removed MatchesPattern from IPathUtilityService / PathUtilityService and updated callers to use PatternMatchingUtility.
  • Expanded/updated unit tests to cover the new matching behavior and APIs.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Updates test utility pattern selection to use PatternMatchingUtility.GetMatchingPattern.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocking for the deleted IPathUtilityService.MatchesPattern API.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Updates tests to the new Compile/CompiledMatcher APIs and adds more matching cases.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Removes MatchesPattern from the path utility contract.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Switches file inclusion + matched-pattern selection to a compiled matcher.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Replaces custom wildcard logic with FileSystemName.MatchesSimpleExpression; adds CompiledMatcher.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes legacy pattern matching implementations.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Uses CompiledMatcher for file filtering and matched-pattern resolution; removes MatchesAnyPattern.

Copilot's findings

Comments suppressed due to low confidence (2)

src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs:214

  • patterns is enumerated multiple times here (string.Join and then PatternMatchingUtility.Compile(patterns)), which can be problematic for lazy/non-repeatable IEnumerable<string> inputs and adds overhead. Consider converting to an array once (e.g., var patternArray = patterns.ToArray()) and using it for both logging and compilation.
            this.logger.LogDebug("Logging patterns {Patterns} for {Root}", string.Join(":", patterns), root.FullName);

            var compiled = PatternMatchingUtility.Compile(patterns);

src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs:236

  • This method compiles patterns and also calls Subscribe(root, patterns), which currently re-enumerates and recompiles patterns again. Materializing patterns once (array) and reusing a single compiled matcher for both filtering and MatchedPattern selection would avoid redundant work and prevents issues if patterns is a single-pass/lazy enumerable.
    public IObservable<ProcessRequest> GetFilteredComponentStreamObservable(DirectoryInfo root, IEnumerable<string> patterns, IComponentRecorder componentRecorder)
    {
        var compiled = PatternMatchingUtility.Compile(patterns);

        var observable = this.Subscribe(root, patterns).OfType<FileInfo>()
            .Select(f => new
  • Files reviewed: 8/8 changed files
  • Comments generated: 1

@jpinz jpinz requested a review from Copilot April 8, 2026 17:45
@jpinz jpinz marked this pull request as ready for review April 8, 2026 17:45
@jpinz jpinz requested a review from a team as a code owner April 8, 2026 17:45
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

👋 Hi! It looks like you modified some files in the Detectors folder.
You may need to bump the detector versions if any of the following scenarios apply:

  • The detector detects more or fewer components than before
  • The detector generates different parent/child graph relationships than before
  • The detector generates different devDependencies values than before

If none of the above scenarios apply, feel free to ignore this comment 🙂

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR centralizes file-pattern matching by replacing custom PathUtilityService logic with a standardized PatternMatchingUtility implementation backed by System.IO.Enumeration.FileSystemName, and updates directory enumeration code paths and tests accordingly.

Changes:

  • Introduces PatternMatchingUtility.CompiledMatcher and updates consumers to use compiled span-based pattern matching.
  • Removes MatchesPattern from IPathUtilityService/PathUtilityService and updates call sites.
  • Expands/updates pattern matching tests to cover more patterns and case-insensitive matching.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Switches test helper pattern selection to PatternMatchingUtility.GetMatchingPattern.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocks for the deleted IPathUtilityService.MatchesPattern API.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Updates tests to use compiled matcher + adds coverage for case-insensitivity and pattern selection.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Removes MatchesPattern from the contract.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Uses a precompiled matcher for filtering and for retrieving the matched pattern.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Replaces manual matching with FileSystemName.MatchesSimpleExpression and adds CompiledMatcher.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Deletes legacy pattern matching implementations.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Converts file scanning/filtering to use compiled matcher (including matched-pattern selection).

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 3

Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs
@jpinz
Copy link
Copy Markdown
Member Author

jpinz commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Copilot AI review requested due to automatic review settings April 8, 2026 18:12
@jpinz jpinz review requested due to automatic review settings April 8, 2026 18:12
Copilot AI review requested due to automatic review settings April 8, 2026 18:12
@jpinz jpinz review requested due to automatic review settings April 8, 2026 18:12
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Implemented the requested updates from that review thread in commit bd19239: centralized duplicate matching logic in PatternMatchingUtility, documented first-match pattern precedence, and updated API visibility for Compile/CompiledMatcher to align with test/public usage. Full tests are passing after the change.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 4myvsblobprodcus32.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 5dkvsblobprodcus355.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 5rqvsblobprodcus385.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/EAC58970BF56570ECF9A3336E1CC2C51/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/D93C69A3F90DACDB68555AD6306FA9CB/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • azuresdkartifacts.blob.core.windows.net
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp (dns block)
  • c78vsblobprodcus322.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/4EB20032E82B2584A5C53CFFE5CD470A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • e7bvsblobprodcus348.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/6159872093532F2B0C5E6E8E99896FA2/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • jd4vsblobprodcus366.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/CDD3F901B58BCEF02488C08DF1C7A1CC/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force dotn�� by/2e77cb38a0e6dc3803102e0eb5adf090f6f56bd927c0d1e8a0f3c9dccba384d0/config.json (dns block)
  • k4kvsblobprodcus344.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/EAC58970BF56570ECF9A3336E1CC2C51/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/D93C69A3F90DACDB68555AD6306FA9CB/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • m16vsblobprodcus374.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/EFA774C66662112D9EC4DF5EF75C0019/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • pdfvsblobprodcus380.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/C8FA87C461E8D947D5E484A1822A0126/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Migrate to efficient glob pattern matching implementation Address review feedback on pattern matcher API, logic deduplication, and precedence docs Apr 8, 2026
Copilot finished work on behalf of jpinz April 8, 2026 18:13
@jpinz jpinz requested a review from Copilot April 8, 2026 18:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the centralized pattern-matching API in Microsoft.ComponentDetection.Common to align visibility with intended usage, deduplicate matching behavior across entry points, and document/enforce first-match-wins precedence when multiple patterns match the same filename.

Changes:

  • Made PatternMatchingUtility.Compile(...) / CompiledMatcher public and consolidated MatchesPattern, GetMatchingPattern, and compiled matching to a single shared implementation.
  • Updated file enumeration and directory walking to use the compiled matcher and to apply explicit first-match-wins pattern precedence.
  • Updated test utilities and unit tests to use the new API and removed usage of IPathUtilityService.MatchesPattern (including removing it from the interface).
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Uses PatternMatchingUtility.GetMatchingPattern instead of instantiating PathUtilityService for test pattern selection.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocks for IPathUtilityService.MatchesPattern since enumeration no longer depends on it.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Expands/updates coverage for compile/match APIs, case-insensitivity, and precedence behavior.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Removes MatchesPattern from the public Contracts interface.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Switches enumeration matching + selected-pattern reporting to CompiledMatcher, documenting first-match-wins behavior.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Introduces public Compile, MatchesPattern, GetMatchingPattern, and shared internal matching helpers.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes MatchesPattern implementations now replaced by PatternMatchingUtility.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Replaces prior per-pattern matching logic with a compiled matcher and dedupes per-file matching in filtered observables.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 3

Comment thread src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs
@jpinz
Copy link
Copy Markdown
Member Author

jpinz commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Applied in commit 836f45a: FastDirectoryWalkerFactory now reuses a single compiled matcher in GetFilteredComponentStreamObservable/subscribe path (no duplicate compile for the same pattern set), and PatternMatchingUtility now throws deterministically when a pattern collection contains null elements (with added tests). No UI changes in this PR, so there is no UI screenshot to provide.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 1javsblobprodcus364.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/70C17A44F0DC17941F22F7FFA31FD262/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 --global /home/REDACTED/.cargo/bin/git (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/3126A99D59DB84356F552B9BC0A2F062/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� assword=$GITHUB_TOKEN&#34;; }; f get/run/containerd/io.containerd.runtime.v2.task/moby/3c35ecdb72a01/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet assword=$GITHUB_TOKEN&#34;; }; f get--log-format dotnet http.https://git/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet (dns block)
  • 1p7vsblobprodcus324.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/A5E8D0CA472852830AF16B02D1DD7226/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force dotn�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/70C17A44F0DC17941F22F7FFA31FD262/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 --global /home/REDACTED/.cargo/bin/git (dns block)
  • 4myvsblobprodcus32.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/B9D91EC3F00925E83B2F176B451EEAFF/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/D47EE5A44C32F70BEBA9A6371300F374/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/CF4B41BED05CC519E28614CCFB1B4E53/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 4vyvsblobprodcus361.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/A5E8D0CA472852830AF16B02D1DD7226/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force dotn�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/70C17A44F0DC17941F22F7FFA31FD262/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 --global /home/REDACTED/.cargo/bin/git (dns block)
  • 5dkvsblobprodcus355.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 5rqvsblobprodcus385.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/EAC58970BF56570ECF9A3336E1CC2C51/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/4EB20032E82B2584A5C53CFFE5CD470A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 6s7vsblobprodcus313.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/D93C69A3F90DACDB68555AD6306FA9CB/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • 7tjvsblobprodcus341.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/CB9CBA9383D5A238E2B9DD721B214239/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • azuresdkartifacts.blob.core.windows.net
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp (dns block)
  • c78vsblobprodcus322.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/D93C69A3F90DACDB68555AD6306FA9CB/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/C8FA87C461E8D947D5E484A1822A0126/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • fdpvsblobprodcus345.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/B20ADDE6A1C400383AAC6F21E747F83C/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� (dns block)
  • frdvsblobprodcus327.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/A576CF6326A01E4F0463D9C7ACE449BE/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force -c submodules | head -n 10 by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 ction/component-detection/test/Microsoft.ComponentDetection.Orchestrator.Tests/bin/Debug/net8.0/console by/62a16bed8d2eb/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet 85d46c4a6e211db0restore (dns block)
  • k4kvsblobprodcus344.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/2D3586D8C912F6D195254B43F0F0042B/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/86123D718A0A7D5E3D8DDB87D50A845A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/4EB20032E82B2584A5C53CFFE5CD470A/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • kmuvsblobprodcus389.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/A5E8D0CA472852830AF16B02D1DD7226/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force dotn�� by/62a16bed8d2ebf1c937cebce3f0299496694cfe33ba2a9d585d46c4a6e211db0 (dns block)
  • pdfvsblobprodcus380.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/C8FA87C461E8D947D5E484A1822A0126/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • s4uvsblobprodcus326.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/E2F72F1A2053363D6E348F396327EAB5/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force bin/�� detection/src/Microsoft.ComponentDetection.Contracts droid/34.0.43/ dotnet r (dns block)
  • v53vsblobprodcus320.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/3126A99D59DB84356F552B9BC0A2F062/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� assword=$GITHUB_TOKEN&#34;; }; f get/run/containerd/io.containerd.runtime.v2.task/moby/3c35ecdb72a01/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet assword=$GITHUB_TOKEN&#34;; }; f get--log-format dotnet http.https://git/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet (dns block)
  • vb4vsblobprodcus33.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/87542D29D2724C99BF713AC607C855F9/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force conf�� sdk-manifests/8.--package by/bbd8023e09de8microsoft.visualstudio.threading.analyzers dotnet by/bbd8023e09de8/tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet 944f8e4163012482restore (dns block)
  • ytvvsblobprodcus310.vsblob.vsassets.io
    • Triggering command: /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/A57A5A89CDBA36A2878C8A42DA58182C/missingpackages_workingdir --packages /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-fe72422a9cf5c763/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Address follow-up review feedback for centralized pattern matching migration Address follow-up review feedback for matcher reuse and null-pattern validation Apr 8, 2026
Copilot finished work on behalf of jpinz April 8, 2026 21:05
@jpinz jpinz requested a review from Copilot April 8, 2026 21:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the centralized file pattern-matching pipeline to reuse compiled matchers across filtering and matched-pattern selection, while making null-pattern handling deterministic and updating test coverage accordingly.

Changes:

  • Reuse a single compiled matcher in FastDirectoryWalkerFactory for both inclusion filtering and selecting the matched pattern.
  • Introduce deterministic ArgumentNullException behavior when any pattern element is null, and standardize matching via FileSystemName.MatchesSimpleExpression(..., ignoreCase: true).
  • Update and expand tests to cover matcher compilation, matching behavior, and null input validation.
Show a summary per file
File Description
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Reuses one compiled matcher per subscription path and avoids recompiling patterns during filtered observable construction.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Adds Compile, MatchesPattern, GetMatchingPattern, and CompiledMatcher with deterministic null validation.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Switches to a compiled matcher for file inclusion and pattern attribution (and removes per-file pattern iteration).
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes local pattern matching logic and forwards (obsolete) MatchesPattern to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Marks MatchesPattern obsolete and updates docs/parameter naming accordingly.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Adds/updates tests for compiled matcher behavior, case-insensitivity, and null validation scenarios.
test/Microsoft.ComponentDetection.Common.Tests/PathUtilityServiceTests.cs Adds a test verifying obsolete PathUtilityService.MatchesPattern forwards to the new utility logic.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocks that are no longer relevant after SafeFileEnumerable no longer calls IPathUtilityService.MatchesPattern.
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Switches pattern selection to PatternMatchingUtility.GetMatchingPattern for consistency with production matching.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs
@jpinz jpinz requested a review from Copilot April 8, 2026 21:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR centralizes wildcard pattern matching by introducing a compiled matcher API, reusing compiled matchers in directory scanning, and adding deterministic validation for null patterns (with tests updated accordingly).

Changes:

  • Replace ad-hoc/path-service pattern checks with PatternMatchingUtility + CompiledMatcher reuse to reduce repeated compilation and matching work.
  • Add deterministic ArgumentNullException behavior for null pattern inputs / null pattern elements.
  • Expand and adjust unit tests to cover Compile(...), MatchesPattern(...), and GetMatchingPattern(...) (including case-insensitivity and null validation).
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Swaps local matching logic to PatternMatchingUtility.GetMatchingPattern(...).
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Updates tests to reflect matcher no longer calling IPathUtilityService.MatchesPattern(...).
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Adds coverage for compiled matcher, matching pattern selection, case-insensitivity, and null validation.
test/Microsoft.ComponentDetection.Common.Tests/PathUtilityServiceTests.cs Verifies obsolete PathUtilityService.MatchesPattern forwards to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Updates doc/comments and marks MatchesPattern obsolete.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Replaces per-pattern iteration with a compiled matcher and pattern selection.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Introduces MatchesPattern, GetMatchingPattern, Compile, and CompiledMatcher using FileSystemName.MatchesSimpleExpression.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes custom matching implementation; forwards obsolete API to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Reuses a single compiled matcher for filtering + matched-pattern selection; adds subscribe overload.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 3

Comment thread src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs
Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors file pattern matching across the repo by centralizing matching logic in PatternMatchingUtility (with a reusable CompiledMatcher) and updating file enumeration to process each matched file once, using first-match pattern priority.

Changes:

  • Introduces PatternMatchingUtility.CompiledMatcher and span-based matching powered by FileSystemName.MatchesSimpleExpression (case-insensitive).
  • Updates directory walking/enumeration to select the first matching pattern per file and avoid duplicate ProcessRequest generation.
  • Modernizes and expands test coverage for matching semantics and null validation; marks IPathUtilityService.MatchesPattern as obsolete and forwards it.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Uses PatternMatchingUtility.GetMatchingPattern instead of PathUtilityService.MatchesPattern in test utilities.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocks for MatchesPattern since matching no longer uses IPathUtilityService.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Updates matcher tests to use Compile/CompiledMatcher and adds additional cases + null validation tests.
test/Microsoft.ComponentDetection.Common.Tests/PathUtilityServiceTests.cs Adds a regression test verifying the obsolete MatchesPattern forwards to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Updates docs and marks MatchesPattern obsolete in favor of PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/FileComponentDetector.cs Documents first-match-wins priority for SearchPatterns.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Compiles patterns once and uses first-match-wins to assign a single pattern per matched file.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Adds MatchesPattern, GetMatchingPattern, and Compile APIs + CompiledMatcher implementation.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes legacy matching implementations; obsolete method forwards to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Reuses compiled matchers and emits one ProcessRequest per matching file with the selected pattern.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 1

Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request continues the repo-wide refactor of file pattern matching to use PatternMatchingUtility.CompiledMatcher for reusable, case-insensitive matching, while updating callers/tests to align with the new “first match wins” semantics and improved null validation.

Changes:

  • Updates directory/file enumeration to compile and reuse matchers instead of re-evaluating patterns repeatedly.
  • Updates tests/utilities to use PatternMatchingUtility APIs and adds coverage for compilation, matching, and null-input validation.
  • Marks legacy IPathUtilityService.MatchesPattern as obsolete and forwards it to PatternMatchingUtility.
Show a summary per file
File Description
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Uses PatternMatchingUtility.GetMatchingPattern to determine the pattern associated with a file in tests.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Removes mocking of legacy MatchesPattern now that matching is handled via compiled matcher.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Adds/updates tests for compiled matcher behavior, case-insensitivity, and null argument validation.
test/Microsoft.ComponentDetection.Common.Tests/PathUtilityServiceTests.cs Verifies obsolete PathUtilityService.MatchesPattern forwards to the new utility.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Updates docs and marks MatchesPattern obsolete in favor of PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/FileComponentDetector.cs Documents “first match wins” priority expectation for SearchPatterns.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Replaces per-pattern matching loops with a compiled matcher and uses first-match priority for MatchedFile.Pattern.
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Introduces MatchesPattern, GetMatchingPattern, and CompiledMatcher backed by FileSystemName.MatchesSimpleExpression.
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes legacy matching logic and forwards obsolete MatchesPattern to the new utility.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Compiles patterns once per call and reuses the matcher for filtering and matched-pattern selection (avoids duplicate compilation).

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 2

Comment thread src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Outdated
Comment thread src/Microsoft.ComponentDetection.Contracts/FileComponentDetector.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the pattern-matching refactor by introducing a reusable compiled matcher abstraction and wiring it through file enumeration and test utilities, while also tightening null validation and clarifying first-match priority semantics.

Changes:

  • Add PatternMatchingUtility.CompiledMatcher (span-based) and new helpers (Compile, MatchesPattern, GetMatchingPattern) backed by FileSystemName.MatchesSimpleExpression(ignoreCase: true).
  • Update file enumeration/filtering to compile patterns once and reuse the matcher; GetFilteredComponentStreamObservable now emits one ProcessRequest per file with the first matching pattern.
  • Update/expand unit tests and forward the obsolete IPathUtilityService.MatchesPattern to PatternMatchingUtility.
Show a summary per file
File Description
src/Microsoft.ComponentDetection.Common/PatternMatchingUtility.cs Introduces CompiledMatcher + null validation and span-based matching via FileSystemName.MatchesSimpleExpression.
src/Microsoft.ComponentDetection.Common/SafeFileEnumerable.cs Compiles patterns once per enumerable and uses first-match-wins for MatchedFile.Pattern.
src/Microsoft.ComponentDetection.Common/FastDirectoryWalkerFactory.cs Reuses a single compiled matcher and returns a single ProcessRequest per matching file (first matching pattern).
src/Microsoft.ComponentDetection.Common/PathUtilityService.cs Removes legacy matcher logic; obsolete MatchesPattern now forwards to PatternMatchingUtility.
src/Microsoft.ComponentDetection.Contracts/IPathUtilityService.cs Marks MatchesPattern obsolete and updates XML docs/parameter naming.
src/Microsoft.ComponentDetection.Contracts/FileComponentDetector.cs Updates SearchPatterns docs to reflect first-match priority and wildcard usage.
test/Microsoft.ComponentDetection.Common.Tests/PatternMatchingUtilityTests.cs Expands matching, case-insensitivity, null validation, and compiled matcher behaviors.
test/Microsoft.ComponentDetection.Common.Tests/SafeFileEnumerableTests.cs Adjusts mocks to reflect removal of IPathUtilityService.MatchesPattern usage.
test/Microsoft.ComponentDetection.Common.Tests/PathUtilityServiceTests.cs Verifies obsolete MatchesPattern forwarding behavior.
test/Microsoft.ComponentDetection.TestsUtilities/DetectorTestUtilityBuilder.cs Uses PatternMatchingUtility.GetMatchingPattern to select the effective pattern in tests.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new

@jpinz jpinz merged commit e0ec95f into main Apr 10, 2026
31 of 32 checks passed
@jpinz jpinz deleted the fix/glob-pattern-matching branch April 10, 2026 16:23
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.0%. Comparing base (c3ef82c) to head (fa02fc2).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@     Coverage Diff      @@
##   main   #1770   +/-   ##
============================
============================

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants