Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix locale-sensitive comparison of UnmatchedArgument error strings #29559

Merged
merged 7 commits into from
Jan 12, 2023
25 changes: 18 additions & 7 deletions src/Cli/dotnet/ParseResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,29 @@ public static void ShowHelp(this ParseResult parseResult)
Parser.Instance.Parse(tokenList).Invoke();
}

private static string StripPlaceholdersFromString(string input) {
baronfel marked this conversation as resolved.
Show resolved Hide resolved
// Find and remove all format placeholder strings (and filled runtime strings!) of the form ['"].*['"]
// from an input string.
// This lets us do fair comparisons against strings that are translated, since the placeholders
// may be in various locations, and may have different quote characters in different languages.
return System.Text.RegularExpressions.Regex.Replace(input, @"['""](.*)['""]", string.Empty);
baronfel marked this conversation as resolved.
Show resolved Hide resolved
}

public static void ShowHelpOrErrorIfAppropriate(this ParseResult parseResult)
{
if (parseResult.Errors.Any())
{
var unrecognizedTokenErrors = parseResult.Errors.Where(error =>
error.Message.Contains(Parser.Instance.Configuration.LocalizationResources.UnrecognizedCommandOrArgument(string.Empty).Replace("'", string.Empty)));
var unrecognizedTokenErrors = parseResult.Errors.Where(error => {
baronfel marked this conversation as resolved.
Show resolved Hide resolved
var strippedError = StripPlaceholdersFromString(error.Message);
var strippedRawResource = StripPlaceholdersFromString(Parser.Instance.Configuration.LocalizationResources.UnrecognizedCommandOrArgument(string.Empty));
return strippedError.Equals(strippedRawResource, StringComparison.OrdinalIgnoreCase);
});
if (parseResult.CommandResult.Command.TreatUnmatchedTokensAsErrors ||
parseResult.Errors.Except(unrecognizedTokenErrors).Any())
{
throw new CommandParsingException(
message: string.Join(Environment.NewLine,
parseResult.Errors.Select(e => e.Message)),
parseResult.Errors.Select(e => e.Message)),
parseResult: parseResult);
}
}
Expand All @@ -60,7 +71,7 @@ public static string RootSubCommandResult(this ParseResult parseResult)

public static bool IsDotnetBuiltInCommand(this ParseResult parseResult)
{
return string.IsNullOrEmpty(parseResult.RootSubCommandResult()) ||
return string.IsNullOrEmpty(parseResult.RootSubCommandResult()) ||
Parser.GetBuiltInCommand(parseResult.RootSubCommandResult()) != null;
}

Expand Down Expand Up @@ -129,7 +140,7 @@ private static string GetSymbolResultValue(ParseResult parseResult, SymbolResult

public static bool BothArchAndOsOptionsSpecified(this ParseResult parseResult) =>
(parseResult.HasOption(CommonOptions.ArchitectureOption) ||
parseResult.HasOption(CommonOptions.LongFormArchitectureOption)) &&
parseResult.HasOption(CommonOptions.LongFormArchitectureOption)) &&
parseResult.HasOption(CommonOptions.OperatingSystemOption);

internal static string GetCommandLineRuntimeIdentifier(this ParseResult parseResult)
Expand Down Expand Up @@ -206,7 +217,7 @@ public static object SafelyGetValueForOption(this ParseResult parseResult, Optio
!parseResult.Errors.Any(e => e.SymbolResult == optionResult))
{
return optionResult.GetValueForOption(optionToGet);
}
}
else {
return default;
}
Expand All @@ -224,7 +235,7 @@ public static T SafelyGetValueForOption<T>(this ParseResult parseResult, Option<
!parseResult.Errors.Any(e => e.SymbolResult == optionResult))
{
return optionResult.GetValueForOption(optionToGet);
}
}
else {
return default;
}
Expand Down