File: Utilities\MSBuildArgumentParser.cs
Web Access
Project: Microsoft.DotNet.Cli.Definitions.csproj (Microsoft.DotNet.Cli.Definitions)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.DotNet.Cli;

internal static class MSBuildArgumentParser
{
    internal static bool IsMultiThreadedSwitch(string argument)
    {
        string unquoted = Unquote(argument);
        int prefixLength = unquoted.StartsWith("--", StringComparison.Ordinal) ? 2
            : unquoted.StartsWith('-') || unquoted.StartsWith('/') ? 1
            : 0;

        if (prefixLength == 0)
        {
            return false;
        }

        int separatorIndex = unquoted.IndexOf(':');
        string name = separatorIndex < 0 ? unquoted[prefixLength..] : unquoted[prefixLength..separatorIndex];
        if (!name.Equals("mt", StringComparison.OrdinalIgnoreCase) &&
            !name.Equals("multiThreaded", StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        if (separatorIndex < 0)
        {
            return true;
        }

        string parameter = unquoted[(separatorIndex + 1)..];
        return parameter.Length == 0 || bool.TryParse(parameter, out _);
    }

    // Match MSBuild's QuotingUtilities.Unquote, including escaped and doubled quotes.
    // https://github.com/dotnet/msbuild/blob/main/src/Framework/Utilities/QuotingUtilities.cs
    private static string Unquote(string argument)
    {
        if (!argument.Contains('"'))
        {
            return argument;
        }

        var result = new StringBuilder(argument.Length);
        bool isQuoted = false;
        int precedingBackslashes = 0;

        for (int i = 0; i < argument.Length; i++)
        {
            switch (argument[i])
            {
                case '\\':
                    precedingBackslashes++;
                    break;

                case '"':
                    result.Append('\\', precedingBackslashes / 2);
                    if (precedingBackslashes % 2 == 0)
                    {
                        if (isQuoted && i + 1 < argument.Length && argument[i + 1] == '"')
                        {
                            result.Append('"');
                            i++;
                        }

                        isQuoted = !isQuoted;
                    }
                    else
                    {
                        result.Append('"');
                    }

                    precedingBackslashes = 0;
                    break;

                default:
                    result.Append('\\', precedingBackslashes);
                    result.Append(argument[i]);
                    precedingBackslashes = 0;
                    break;
            }
        }

        return result.Append('\\', precedingBackslashes).ToString();
    }
}