Skip to content

Commit a73379b

Browse files
authored
CmdLine parsing was extracted from XMake and the implementation is visible to dotnet (#12704)
### Context In some cases dotnet needs to process MSBuild cmdline switches including response files. ### Changes Made The parsing logic was pulled out from XMake to isolate it in the internal type, making it easily reusable in the .NET SDK project. ### Testing All existing tests are passing. ### Notes The goal of this PR isn’t to refactor the entire API—that’s something we can consider tackling later on.
1 parent a110114 commit a73379b

File tree

8 files changed

+706
-638
lines changed

8 files changed

+706
-638
lines changed

src/MSBuild.UnitTests/CommandLineSwitches_Tests.cs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ public void FeatureAvailibilitySwitchIdentificationTest(string switchName)
622622
public void TargetsSwitchParameter()
623623
{
624624
CommandLineSwitches switches = new CommandLineSwitches();
625-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/targets:targets.txt" }, switches);
625+
CommandLineParser parser = new CommandLineParser();
626+
parser.GatherCommandLineSwitches(new List<string>() { "/targets:targets.txt" }, switches);
626627

627628
switches.HaveErrors().ShouldBeFalse();
628629
switches[CommandLineSwitches.ParameterizedSwitch.Targets].ShouldBe(new[] { "targets.txt" });
@@ -632,7 +633,8 @@ public void TargetsSwitchParameter()
632633
public void TargetsSwitchDoesNotSupportMultipleOccurrences()
633634
{
634635
CommandLineSwitches switches = new CommandLineSwitches();
635-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/targets /targets" }, switches);
636+
CommandLineParser parser = new CommandLineParser();
637+
parser.GatherCommandLineSwitches(new List<string>() { "/targets /targets" }, switches);
636638

637639
switches.HaveErrors().ShouldBeTrue();
638640
}
@@ -709,8 +711,9 @@ public void LowPrioritySwitchIdentificationTests(string lowpriority)
709711
public void GraphBuildSwitchCanHaveParameters()
710712
{
711713
CommandLineSwitches switches = new CommandLineSwitches();
714+
CommandLineParser parser = new CommandLineParser();
712715

713-
MSBuildApp.GatherCommandLineSwitches(new List<string> { "/graph", "/graph:true; NoBuild ;; ;", "/graph:foo" }, switches);
716+
parser.GatherCommandLineSwitches(new List<string> { "/graph", "/graph:true; NoBuild ;; ;", "/graph:foo" }, switches);
714717

715718
switches[CommandLineSwitches.ParameterizedSwitch.GraphBuild].ShouldBe(new[] { "true", " NoBuild ", " ", "foo" });
716719

@@ -721,8 +724,9 @@ public void GraphBuildSwitchCanHaveParameters()
721724
public void GraphBuildSwitchCanBeParameterless()
722725
{
723726
CommandLineSwitches switches = new CommandLineSwitches();
727+
CommandLineParser parser = new CommandLineParser();
724728

725-
MSBuildApp.GatherCommandLineSwitches(new List<string> { "/graph" }, switches);
729+
parser.GatherCommandLineSwitches(new List<string> { "/graph" }, switches);
726730

727731
switches[CommandLineSwitches.ParameterizedSwitch.GraphBuild].ShouldBe(Array.Empty<string>());
728732

@@ -733,8 +737,9 @@ public void GraphBuildSwitchCanBeParameterless()
733737
public void InputResultsCachesSupportsMultipleOccurrence()
734738
{
735739
CommandLineSwitches switches = new CommandLineSwitches();
740+
CommandLineParser parser = new CommandLineParser();
736741

737-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/irc", "/irc:a;b", "/irc:c;d" }, switches);
742+
parser.GatherCommandLineSwitches(new List<string>() { "/irc", "/irc:a;b", "/irc:c;d" }, switches);
738743

739744
switches[CommandLineSwitches.ParameterizedSwitch.InputResultsCaches].ShouldBe(new[] { null, "a", "b", "c", "d" });
740745

@@ -745,8 +750,9 @@ public void InputResultsCachesSupportsMultipleOccurrence()
745750
public void OutputResultsCache()
746751
{
747752
CommandLineSwitches switches = new CommandLineSwitches();
753+
CommandLineParser parser = new CommandLineParser();
748754

749-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/orc:a" }, switches);
755+
parser.GatherCommandLineSwitches(new List<string>() { "/orc:a" }, switches);
750756

751757
switches[CommandLineSwitches.ParameterizedSwitch.OutputResultsCache].ShouldBe(new[] { "a" });
752758

@@ -757,8 +763,9 @@ public void OutputResultsCache()
757763
public void OutputResultsCachesDoesNotSupportMultipleOccurrences()
758764
{
759765
CommandLineSwitches switches = new CommandLineSwitches();
766+
CommandLineParser parser = new CommandLineParser();
760767

761-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "/orc:a", "/orc:b" }, switches);
768+
parser.GatherCommandLineSwitches(new List<string>() { "/orc:a", "/orc:b" }, switches);
762769

763770
switches.HaveErrors().ShouldBeTrue();
764771
}
@@ -1288,8 +1295,9 @@ public void ExtractAnyLoggerParameterPickLast()
12881295
public void ProcessWarnAsErrorSwitchNotSpecified()
12891296
{
12901297
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1298+
CommandLineParser parser = new CommandLineParser();
12911299

1292-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "" }), commandLineSwitches);
1300+
parser.GatherCommandLineSwitches(new List<string>(new[] { "" }), commandLineSwitches);
12931301

12941302
Assert.Null(MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches));
12951303
}
@@ -1303,8 +1311,9 @@ public void ProcessWarnAsErrorSwitchWithCodes()
13031311
ISet<string> expectedWarningsAsErrors = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a", "B", "c", "D", "e" };
13041312

13051313
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1314+
CommandLineParser parser = new CommandLineParser();
13061315

1307-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
1316+
parser.GatherCommandLineSwitches(new List<string>(new[]
13081317
{
13091318
"\"/warnaserror: a,B ; c \"", // Leading, trailing, leading and trailing whitespace
13101319
"/warnaserror:A,b,C", // Repeats of different case
@@ -1328,8 +1337,9 @@ public void ProcessWarnAsErrorSwitchWithCodes()
13281337
public void ProcessWarnAsErrorSwitchEmptySwitchClearsSet()
13291338
{
13301339
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1340+
CommandLineParser parser = new CommandLineParser();
13311341

1332-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
1342+
parser.GatherCommandLineSwitches(new List<string>(new[]
13331343
{
13341344
"/warnaserror:a;b;c",
13351345
"/warnaserror",
@@ -1351,8 +1361,9 @@ public void ProcessWarnAsErrorSwitchValuesAfterEmptyAddOn()
13511361
ISet<string> expectedWarningsAsErors = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "e", "f", "g" };
13521362

13531363
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1364+
CommandLineParser parser = new CommandLineParser();
13541365

1355-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
1366+
parser.GatherCommandLineSwitches(new List<string>(new[]
13561367
{
13571368
"/warnaserror:a;b;c",
13581369
"/warnaserror",
@@ -1373,8 +1384,9 @@ public void ProcessWarnAsErrorSwitchValuesAfterEmptyAddOn()
13731384
public void ProcessWarnAsErrorSwitchEmpty()
13741385
{
13751386
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1387+
CommandLineParser parser = new CommandLineParser();
13761388

1377-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/warnaserror" }), commandLineSwitches);
1389+
parser.GatherCommandLineSwitches(new List<string>(new[] { "/warnaserror" }), commandLineSwitches);
13781390

13791391
ISet<string> actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
13801392

@@ -1390,10 +1402,11 @@ public void ProcessWarnAsErrorSwitchEmpty()
13901402
public void ProcessWarnAsMessageSwitchEmpty()
13911403
{
13921404
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1405+
CommandLineParser parser = new CommandLineParser();
13931406

13941407
// Set "expanded" content to match the placeholder so the verify can use the exact resource string as "expected."
13951408
string command = "{0}";
1396-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/warnasmessage" }), commandLineSwitches, command);
1409+
parser.GatherCommandLineSwitches(new List<string>(new[] { "/warnasmessage" }), commandLineSwitches, command);
13971410

13981411
VerifySwitchError(commandLineSwitches, "/warnasmessage", AssemblyResources.GetString("MissingWarnAsMessageParameterError"));
13991412
}
@@ -1410,13 +1423,15 @@ public void ProcessEnvironmentVariableSwitch()
14101423
env.SetEnvironmentVariable("ENVIRONMENTVARIABLE", string.Empty);
14111424

14121425
CommandLineSwitches commandLineSwitches = new();
1426+
CommandLineParser parser = new CommandLineParser();
1427+
14131428
string fullCommandLine = "msbuild validProject.csproj %ENVIRONMENTVARIABLE%";
1414-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "validProject.csproj", "%ENVIRONMENTVARIABLE%" }, commandLineSwitches, fullCommandLine);
1429+
parser.GatherCommandLineSwitches(new List<string>() { "validProject.csproj", "%ENVIRONMENTVARIABLE%" }, commandLineSwitches, fullCommandLine);
14151430
VerifySwitchError(commandLineSwitches, "%ENVIRONMENTVARIABLE%", String.Format(AssemblyResources.GetString("EnvironmentVariableAsSwitch"), fullCommandLine));
14161431

14171432
commandLineSwitches = new();
14181433
fullCommandLine = "msbuild %ENVIRONMENTVARIABLE% validProject.csproj";
1419-
MSBuildApp.GatherCommandLineSwitches(new List<string>() { "%ENVIRONMENTVARIABLE%", "validProject.csproj" }, commandLineSwitches, fullCommandLine);
1434+
parser.GatherCommandLineSwitches(new List<string>() { "%ENVIRONMENTVARIABLE%", "validProject.csproj" }, commandLineSwitches, fullCommandLine);
14201435
VerifySwitchError(commandLineSwitches, "%ENVIRONMENTVARIABLE%", String.Format(AssemblyResources.GetString("EnvironmentVariableAsSwitch"), fullCommandLine));
14211436
}
14221437
}
@@ -1430,8 +1445,9 @@ public void ProcessWarnAsMessageSwitchWithCodes()
14301445
ISet<string> expectedWarningsAsMessages = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a", "B", "c", "D", "e" };
14311446

14321447
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1448+
CommandLineParser parser = new CommandLineParser();
14331449

1434-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[]
1450+
parser.GatherCommandLineSwitches(new List<string>(new[]
14351451
{
14361452
"\"/warnasmessage: a,B ; c \"", // Leading, trailing, leading and trailing whitespace
14371453
"/warnasmessage:A,b,C", // Repeats of different case
@@ -1455,8 +1471,9 @@ public void ProcessWarnAsMessageSwitchWithCodes()
14551471
public void ProcessProfileEvaluationEmpty()
14561472
{
14571473
CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
1474+
CommandLineParser parser = new CommandLineParser();
14581475

1459-
MSBuildApp.GatherCommandLineSwitches(new List<string>(new[] { "/profileevaluation" }), commandLineSwitches);
1476+
parser.GatherCommandLineSwitches(new List<string>(new[] { "/profileevaluation" }), commandLineSwitches);
14601477
commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.ProfileEvaluation][0].ShouldBe("no-file");
14611478
}
14621479

0 commit comments

Comments
 (0)