Skip to content
Draft
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d88d0ce
Initial plan for issue
Copilot May 27, 2025
1443d5e
Optimize performance of CommandLineOptionsValidator
Copilot May 27, 2025
85ffb88
Remove PerformanceSensitiveAttribute usage
Copilot May 27, 2025
39d6db5
Fix code formatting in CommandLineOptionsValidator.cs
Copilot May 27, 2025
78e96f8
Add blank line after conditional block in CommandLineOptionsValidator.cs
Copilot May 27, 2025
975d2d6
Fix whitespace formatting in CommandLineOptionsValidator.cs
Copilot May 27, 2025
86c987c
Replace var with explicit type in foreach loop at line 114
Copilot Jun 1, 2025
2e2ee02
Replace var with explicit types and fix whitespace formatting
Copilot Jun 1, 2025
07a4700
Fix formatting: move string.Format to separate line with proper inden…
Copilot Jun 1, 2025
6c344de
Replace var with explicit types in ValidateOptionsAreNotDuplicated me…
Copilot Jun 1, 2025
3ba2fb0
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 1, 2025
e1369e7
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 1, 2025
780fd3b
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 1, 2025
fe102f2
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 1, 2025
cae2a1b
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 2, 2025
97c8299
Update CommandLineOptionsValidator.cs
Youssef1313 Jun 2, 2025
63ab4f7
Add more tests
Evangelink Feb 22, 2026
3f0ce4e
Merge branch 'main' into copilot/fix-5651
Youssef1313 Mar 31, 2026
1cc37c3
Update CommandLineOptionsValidator.cs
Youssef1313 Apr 1, 2026
a470f0c
Update CommandLineOptionsValidator.cs
Youssef1313 Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Testing.Platform.Extensions;
using Microsoft.Testing.Platform.Extensions.CommandLine;
using Microsoft.Testing.Platform.Helpers;
Expand Down Expand Up @@ -101,40 +109,69 @@
Dictionary<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> extensionOptionsByProvider,
Dictionary<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> systemOptionsByProvider)
{
IEnumerable<string> allExtensionOptions = extensionOptionsByProvider.Values.SelectMany(x => x).Select(x => x.Name).Distinct();
IEnumerable<string> allSystemOptions = systemOptionsByProvider.Values.SelectMany(x => x).Select(x => x.Name).Distinct();

IEnumerable<string> invalidReservedOptions = allSystemOptions.Intersect(allExtensionOptions);
if (invalidReservedOptions.Any())
// Create a HashSet of all system option names for faster lookup
HashSet<string> systemOptionNames = new();
foreach (var provider in systemOptionsByProvider)
Comment thread
Evangelink marked this conversation as resolved.
Outdated
{
var stringBuilder = new StringBuilder();
foreach (string reservedOption in invalidReservedOptions)
foreach (var option in provider.Value)
Comment thread
Evangelink marked this conversation as resolved.
Outdated
{
IEnumerable<string> faultyProviderNames = extensionOptionsByProvider.Where(tuple => tuple.Value.Any(x => x.Name == reservedOption)).Select(tuple => tuple.Key.DisplayName);
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionIsReserved, reservedOption, string.Join("', '", faultyProviderNames)));
systemOptionNames.Add(option.Name);
}
}

return ValidationResult.Invalid(stringBuilder.ToTrimmedString());
StringBuilder? stringBuilder = null;
foreach (var provider in extensionOptionsByProvider)
Comment thread
Evangelink marked this conversation as resolved.
Outdated
{
foreach (var option in provider.Value)
{
if (systemOptionNames.Contains(option.Name))
{
stringBuilder ??= new StringBuilder();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture,

Check failure on line 130 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L130

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(130,89): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 130 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L130

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(130,89): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 130 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L130

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(130,89): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 130 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L130

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(130,89): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 130 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L130

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(130,89): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
PlatformResources.CommandLineOptionIsReserved,

Check failure on line 131 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L131

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(131,71): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 131 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L131

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(131,71): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 131 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L131

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(131,71): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 131 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L131

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(131,71): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 131 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L131

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(131,71): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
option.Name,

Check failure on line 132 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L132

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(132,37): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 132 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L132

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(132,37): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 132 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L132

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(132,37): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 132 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L132

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(132,37): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 132 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L132

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(132,37): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
provider.Key.DisplayName));
}
}
}

Comment on lines +140 to 152
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

ValidateExtensionOptionsDoNotContainReservedOptions now emits one error line per (provider, option) and only includes the current provider’s DisplayName. Previously it emitted one line per reserved option and included all offending providers, so this is a behavior/error-message regression (and will get worse if the resource string is corrected to use the provider placeholder). Consider aggregating by option name (e.g., option -> list of providers) and formatting a single message per reserved option with the complete provider list.

Suggested change
StringBuilder? stringBuilder = null;
foreach (KeyValuePair<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> provider in extensionOptionsByProvider)
{
foreach (CommandLineOption option in provider.Value)
{
if (systemOptionNames.Contains(option.Name))
{
stringBuilder ??= new StringBuilder();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionIsReserved, option.Name, provider.Key.DisplayName));
}
}
}
// Aggregate reserved options by name and track all offending providers
Dictionary<string, List<ICommandLineOptionsProvider>> reservedOptionToProviders = new();
foreach (KeyValuePair<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> kvp in extensionOptionsByProvider)
{
ICommandLineOptionsProvider provider = kvp.Key;
foreach (CommandLineOption option in kvp.Value)
{
if (systemOptionNames.Contains(option.Name))
{
if (!reservedOptionToProviders.TryGetValue(option.Name, out List<ICommandLineOptionsProvider>? providers))
{
providers = new List<ICommandLineOptionsProvider>();
reservedOptionToProviders[option.Name] = providers;
}
providers.Add(provider);
}
}
}
StringBuilder? stringBuilder = null;
foreach (KeyValuePair<string, List<ICommandLineOptionsProvider>> kvp in reservedOptionToProviders)
{
string reservedOption = kvp.Key;
stringBuilder ??= new StringBuilder();
IEnumerable<string> faultyProvidersDisplayNames = kvp.Value.Select(p => p.DisplayName);
stringBuilder.AppendLine(string.Format(
CultureInfo.InvariantCulture,
PlatformResources.CommandLineOptionIsReserved,
reservedOption,
string.Join("', '", faultyProvidersDisplayNames)));
}

Copilot uses AI. Check for mistakes.
return ValidationResult.Valid();
return stringBuilder?.Length > 0
? ValidationResult.Invalid(stringBuilder.ToTrimmedString())
: ValidationResult.Valid();
}

private static ValidationResult ValidateOptionsAreNotDuplicated(
Dictionary<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> extensionOptionsByProvider)
{
IEnumerable<string> duplications = extensionOptionsByProvider.Values.SelectMany(x => x)
.Select(x => x.Name)
.GroupBy(x => x)
.Where(x => x.Skip(1).Any())
.Select(x => x.Key);

// Use a dictionary to track option names and their providers
Dictionary<string, List<ICommandLineOptionsProvider>> optionNameToProviders = new();

Check failure on line 148 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L148

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(148,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 148 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L148

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(148,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 148 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L148

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(148,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 148 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L148

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(148,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 148 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L148

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(148,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
foreach (var kvp in extensionOptionsByProvider)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
{
var provider = kvp.Key;
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
foreach (var option in kvp.Value)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
{
string name = option.Name;
if (!optionNameToProviders.TryGetValue(name, out var providers))
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
{
providers = new List<ICommandLineOptionsProvider>();
optionNameToProviders[name] = providers;
}
Comment thread
Youssef1313 marked this conversation as resolved.
providers.Add(provider);
}
}
Comment on lines +161 to +177
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

The new duplication tracking counts providers, not distinct providers. If a single provider declares the same option name multiple times, kvp.Value.Count > 1 will be true and the error message may list the same provider multiple times. To preserve the previous behavior (providers listed once), store providers in a HashSet<ICommandLineOptionsProvider> (or store display names in a HashSet<string>) per option name, or apply Distinct() before counting and formatting.

Copilot uses AI. Check for mistakes.

Check failure on line 163 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L163

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(163,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 163 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L163

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(163,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 163 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L163

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(163,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 163 in src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build MacOS Release)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs#L163

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(163,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
// Check for duplications
StringBuilder? stringBuilder = null;
foreach (string duplicatedOption in duplications)
foreach (var kvp in optionNameToProviders)
{
IEnumerable<string> faultyProvidersDisplayNames = extensionOptionsByProvider.Where(tuple => tuple.Value.Any(x => x.Name == duplicatedOption)).Select(tuple => tuple.Key.DisplayName);
stringBuilder ??= new();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionIsDeclaredByMultipleProviders, duplicatedOption, string.Join("', '", faultyProvidersDisplayNames)));
if (kvp.Value.Count > 1)
{
string duplicatedOption = kvp.Key;
stringBuilder ??= new();
IEnumerable<string> faultyProvidersDisplayNames = kvp.Value.Select(p => p.DisplayName);
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionIsDeclaredByMultipleProviders, duplicatedOption, string.Join("', '", faultyProvidersDisplayNames)));
}
Comment on lines +161 to +189
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

ValidateOptionsAreNotDuplicated tracks providers in a List and counts duplicates based on total entries, which will incorrectly report “multiple extensions” if a single provider returns the same option name more than once (and can also print the same provider name multiple times). Track distinct providers per option (e.g., HashSet) and base the duplication decision / formatted provider list on the distinct-provider count.

Copilot uses AI. Check for mistakes.
}
Comment on lines +181 to 190
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

The new duplication tracking counts providers, not distinct providers. If a single provider declares the same option name multiple times, kvp.Value.Count > 1 will be true and the error message may list the same provider multiple times. To preserve the previous behavior (providers listed once), store providers in a HashSet<ICommandLineOptionsProvider> (or store display names in a HashSet<string>) per option name, or apply Distinct() before counting and formatting.

Copilot uses AI. Check for mistakes.

return stringBuilder?.Length > 0
Expand All @@ -147,10 +184,28 @@
Dictionary<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> extensionOptionsByProvider,
Dictionary<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> systemOptionsByProvider)
{
// Create a HashSet of all valid option names for faster lookup
HashSet<string> validOptionNames = new();
foreach (var provider in extensionOptionsByProvider)
{
foreach (var option in provider.Value)
{
validOptionNames.Add(option.Name);
}
}

Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
foreach (var provider in systemOptionsByProvider)
{
foreach (var option in provider.Value)
{
validOptionNames.Add(option.Name);
}
}

StringBuilder? stringBuilder = null;
foreach (CommandLineParseOption optionRecord in parseResult.Options)
{
if (!extensionOptionsByProvider.Union(systemOptionsByProvider).Any(tuple => tuple.Value.Any(x => x.Name == optionRecord.Name)))
if (!validOptionNames.Contains(optionRecord.Name))
{
stringBuilder ??= new();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineUnknownOption, optionRecord.Name));
Expand All @@ -166,7 +221,7 @@
CommandLineParseResult parseResult,
Dictionary<string, (ICommandLineOptionsProvider Provider, CommandLineOption Option)> providerAndOptionByOptionName)
{
StringBuilder stringBuilder = new();
StringBuilder? stringBuilder = null;
foreach (IGrouping<string, CommandLineParseOption> groupedOptions in parseResult.Options.GroupBy(x => x.Name))
{
// getting the arguments count for an option.
Expand All @@ -181,19 +236,22 @@

if (arity > option.Arity.Max && option.Arity.Max == 0)
{
stringBuilder ??= new();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionExpectsNoArguments, optionName, provider.DisplayName, provider.Uid));
}
else if (arity < option.Arity.Min)
{
stringBuilder ??= new();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionExpectsAtLeastArguments, optionName, provider.DisplayName, provider.Uid, option.Arity.Min));
}
else if (arity > option.Arity.Max)
{
stringBuilder ??= new();
stringBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineOptionExpectsAtMostArguments, optionName, provider.DisplayName, provider.Uid, option.Arity.Max));
}
}

return stringBuilder.Length > 0
return stringBuilder?.Length > 0
? ValidationResult.Invalid(stringBuilder.ToTrimmedString())
: ValidationResult.Valid();
}
Expand Down Expand Up @@ -254,7 +312,22 @@
}

private static string ToTrimmedString(this StringBuilder stringBuilder)
#pragma warning disable RS0030 // Do not use banned APIs
=> stringBuilder.ToString().TrimEnd(Environment.NewLine.ToCharArray());
#pragma warning restore RS0030 // Do not use banned APIs
{
// Use a more efficient approach to trim without creating unnecessary intermediate strings
string result = stringBuilder.ToString();
int end = result.Length;

Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
// Find the last non-whitespace char
while (end > 0)
{
char c = result[end - 1];
if (c != '\r' && c != '\n')
{
break;
}
Comment thread
Youssef1313 marked this conversation as resolved.
Comment thread
Youssef1313 marked this conversation as resolved.
end--;
}

Comment thread
Youssef1313 marked this conversation as resolved.
Outdated
return end == result.Length ? result : result.Substring(0, end);
}
Comment on lines 329 to +348
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

Despite the comment, this still potentially allocates twice (ToString() + Substring()), so the allocation win vs TrimEnd(...) may be limited. If the goal is to reduce allocations, consider trimming by mutating the StringBuilder length (remove trailing \\r/\\n characters from the builder) before calling ToString(), which guarantees a single final string allocation. Also, the comment says 'non-whitespace' but the logic only trims CR/LF; update the comment to match behavior.

Copilot uses AI. Check for mistakes.
}
Loading