Skip to content
Closed
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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 (KeyValuePair<ICommandLineOptionsProvider, IReadOnlyCollection<CommandLineOption>> provider in systemOptionsByProvider)
Comment on lines 126 to +132
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.

PR description mentions adding a PerformanceSensitive attribute and annotating validation methods, but no such attributes appear in this change set. Either the description should be updated, or the attribute additions are missing from the PR.

Copilot uses AI. Check for mistakes.
{
var stringBuilder = new StringBuilder();
foreach (string reservedOption in invalidReservedOptions)
foreach (CommandLineOption option in provider.Value)
{
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 (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,

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,60): error SA1116: (NETCORE_ENGINEERING_TELEMETRY=Build) The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md)

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,60): error SA1116: (NETCORE_ENGINEERING_TELEMETRY=Build) The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md)

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,60): error SA1116: (NETCORE_ENGINEERING_TELEMETRY=Build) The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md)

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,60): error SA1116: (NETCORE_ENGINEERING_TELEMETRY=Build) The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md)

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,60): error SA1116: (NETCORE_ENGINEERING_TELEMETRY=Build) The parameters should begin on the line after the declaration, whenever the parameter span across multiple lines (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1116.md)
PlatformResources.CommandLineOptionIsReserved,
option.Name,
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();
foreach (var kvp in extensionOptionsByProvider)

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,18): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

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,18): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

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,18): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

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,18): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

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,18): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)
{
var provider = kvp.Key;

Check failure on line 150 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#L150

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(150,13): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 150 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#L150

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(150,13): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 150 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#L150

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(150,13): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 150 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#L150

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(150,13): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 150 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#L150

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(150,13): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)
foreach (var option in kvp.Value)

Check failure on line 151 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#L151

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(151,22): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 151 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#L151

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(151,22): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 151 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#L151

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(151,22): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 151 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#L151

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(151,22): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 151 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#L151

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(151,22): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)
{
string name = option.Name;
if (!optionNameToProviders.TryGetValue(name, out var providers))

Check failure on line 154 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#L154

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(154,66): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 154 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#L154

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(154,66): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 154 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#L154

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(154,66): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)

Check failure on line 154 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#L154

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineOptionsValidator.cs(154,66): error IDE0008: (NETCORE_ENGINEERING_TELEMETRY=Build) Use explicit type instead of 'var' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008)
{
providers = new List<ICommandLineOptionsProvider>();
optionNameToProviders[name] = providers;
}

providers.Add(provider);
}
}

// 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.
}

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);
}
}

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,23 @@
}

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;

// Find the last non-whitespace char
while (end > 0)
{
char c = result[end - 1];
if (c != '\r' && c != '\n')
{
break;
}

end--;
}

return end == result.Length ? result : result.Substring(0, end);
}
}
Loading