Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
159 changes: 144 additions & 15 deletions src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,24 @@ namespace Microsoft.DotNet.Cli.Utils;
/// </summary>
public sealed class MSBuildArgs
{
private MSBuildArgs(ReadOnlyDictionary<string, string>? properties, ReadOnlyDictionary<string, string>? restoreProperties, string[]? targets, VerbosityOptions? verbosity, string[]? otherMSBuildArgs)
private MSBuildArgs(
ReadOnlyDictionary<string, string>? properties,
ReadOnlyDictionary<string, string>? restoreProperties,
string[]? targets,
string[]? getProperty,
string[]? getItem,
string[]? getTargetResult,
string[]? getResultOutputFile,
VerbosityOptions? verbosity,
string[]? otherMSBuildArgs)
{
GlobalProperties = properties;
RestoreGlobalProperties = restoreProperties;
RequestedTargets = targets;
GetProperty = getProperty;
GetItem = getItem;
GetTargetResult = getTargetResult;
GetResultOutputFile = getResultOutputFile;
Verbosity = verbosity;
OtherMSBuildArgs = otherMSBuildArgs is not null
? [.. otherMSBuildArgs]
Expand All @@ -37,6 +50,15 @@ private MSBuildArgs(ReadOnlyDictionary<string, string>? properties, ReadOnlyDict
/// The ordered list of targets that should be passed to MSBuild.
/// </summary>
public string[]? RequestedTargets { get; }

public string[]? GetProperty { get; }

public string[]? GetItem { get; }

public string[]? GetTargetResult { get; }

public string[]? GetResultOutputFile { get; }

public VerbosityOptions? Verbosity { get; }

/// <summary>
Expand Down Expand Up @@ -70,6 +92,10 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedA
var globalProperties = parseResult.GetResult("--property") is OptionResult propResult ? propResult.GetValueOrDefault<ReadOnlyDictionary<string, string>?>() : null;
var restoreProperties = parseResult.GetResult("--restoreProperty") is OptionResult restoreResult ? restoreResult.GetValueOrDefault<ReadOnlyDictionary<string, string>?>() : null;
var requestedTargets = parseResult.GetResult("--target") is OptionResult targetResult ? targetResult.GetValueOrDefault<string[]?>() : null;
var getProperty = TryGetValue<string[]>("--getProperty");
var getItem = TryGetValue<string[]?>("--getItem");
var getTargetResult = TryGetValue<string[]?>("--getTargetResult");
var getResultOutputFile = TryGetValue<string[]?>("--getResultOutputFile");
var verbosity = parseResult.GetResult("--verbosity") is OptionResult verbosityResult
? verbosityResult.GetValueOrDefault<VerbosityOptions?>()
: null;
Expand All @@ -78,26 +104,35 @@ public static MSBuildArgs AnalyzeMSBuildArguments(IEnumerable<string> forwardedA
properties: globalProperties,
restoreProperties: restoreProperties,
targets: requestedTargets,
getProperty: getProperty,
getItem: getItem,
getTargetResult: getTargetResult,
getResultOutputFile: getResultOutputFile,
otherMSBuildArgs: otherMSBuildArgs,
verbosity: verbosity);

T? TryGetValue<T>(string name)
{
return options.Any(o => o.Name == name) ? parseResult.GetValue<T>(name) : default;
}
}


public static MSBuildArgs FromProperties(ReadOnlyDictionary<string, string>? properties)
{
return new MSBuildArgs(properties, null, null, null, null);
return new MSBuildArgs(properties, null, null, null, null, null, null, null, null);
}

public static MSBuildArgs FromOtherArgs(params ReadOnlySpan<string> args)
{
return new MSBuildArgs(null, null, null, null, args.ToArray());
return new MSBuildArgs(null, null, null, null, null, null, null, null, args.ToArray());
}
public static MSBuildArgs FromVerbosity(VerbosityOptions verbosity)
{
return new MSBuildArgs(null, null, null, verbosity, null);
return new MSBuildArgs(null, null, null, null, null, null, null, verbosity, null);
}

public static readonly MSBuildArgs ForHelp = new(null, null, null, null, ["--help"]);
public static readonly MSBuildArgs ForHelp = new(null, null, null, null, null, null, null, null, ["--help"]);

/// <summary>
/// Completely replaces the MSBuild arguments with the provided <paramref name="newArgs"/>.
Expand All @@ -108,6 +143,10 @@ public MSBuildArgs CloneWithExplicitArgs(string[] newArgs)
properties: GlobalProperties,
restoreProperties: RestoreGlobalProperties,
targets: RequestedTargets,
getProperty: GetProperty,
getItem: GetItem,
getTargetResult: GetTargetResult,
getResultOutputFile: GetResultOutputFile,
otherMSBuildArgs: newArgs,
verbosity: Verbosity);
}
Expand All @@ -120,63 +159,153 @@ public MSBuildArgs CloneWithAdditionalArgs(params string[] additionalArgs)
if (additionalArgs is null || additionalArgs.Length == 0)
{
// If there are no additional args, we can just return the current instance.
return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, RequestedTargets, Verbosity, [.. OtherMSBuildArgs, .. additionalArgs]);
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
[.. OtherMSBuildArgs, .. additionalArgs]);
}

public MSBuildArgs CloneWithAdditionalRestoreProperties(ReadOnlyDictionary<string, string>? additionalRestoreProperties)
{
if (additionalRestoreProperties is null || additionalRestoreProperties.Count == 0)
{
// If there are no additional restore properties, we can just return the current instance.
return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}
if (RestoreGlobalProperties is null)
{
return new MSBuildArgs(GlobalProperties, additionalRestoreProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
additionalRestoreProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

var newRestoreProperties = new Dictionary<string, string>(RestoreGlobalProperties, StringComparer.OrdinalIgnoreCase);
foreach (var kvp in additionalRestoreProperties)
{
newRestoreProperties[kvp.Key] = kvp.Value;
}
return new MSBuildArgs(GlobalProperties, new(newRestoreProperties), RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
new(newRestoreProperties),
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

public MSBuildArgs CloneWithAdditionalProperties(ReadOnlyDictionary<string, string>? additionalProperties)
{
if (additionalProperties is null || additionalProperties.Count == 0)
{
// If there are no additional properties, we can just return the current instance.
return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}
if (GlobalProperties is null)
{
return new MSBuildArgs(additionalProperties, RestoreGlobalProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
additionalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

var newProperties = new Dictionary<string, string>(GlobalProperties, StringComparer.OrdinalIgnoreCase);
foreach (var kvp in additionalProperties)
{
newProperties[kvp.Key] = kvp.Value;
}
return new MSBuildArgs(new(newProperties), RestoreGlobalProperties, RequestedTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
new(newProperties),
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

public MSBuildArgs CloneWithAdditionalTargets(params ReadOnlySpan<string> additionalTargets)
{
string[] newTargets = RequestedTargets is not null
? [.. RequestedTargets, .. additionalTargets]
: [.. additionalTargets];
return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, newTargets, Verbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
newTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
Verbosity,
OtherMSBuildArgs.ToArray());
}

public MSBuildArgs CloneWithVerbosity(VerbosityOptions newVerbosity)
{
return new MSBuildArgs(GlobalProperties, RestoreGlobalProperties, RequestedTargets, newVerbosity, OtherMSBuildArgs.ToArray());
return new MSBuildArgs(
GlobalProperties,
RestoreGlobalProperties,
RequestedTargets,
GetProperty,
GetItem,
GetTargetResult,
GetResultOutputFile,
newVerbosity,
OtherMSBuildArgs.ToArray());
}

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Build/BuildCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ private static Command ConstructCommand()
command.Options.Add(CommonOptions.OperatingSystemOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
command.Options.Add(TargetOption);
command.Options.Add(CommonOptions.GetPropertyOption);
command.Options.Add(CommonOptions.GetItemOption);
command.Options.Add(CommonOptions.GetTargetResultOption);
command.Options.Add(CommonOptions.GetResultOutputFileOption);

command.SetAction(BuildCommand.Run);

Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ private static Command ConstructCommand()
command.Options.Add(NoLogoOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
command.Options.Add(TargetOption);
command.Options.Add(CommonOptions.GetPropertyOption);
command.Options.Add(CommonOptions.GetItemOption);
command.Options.Add(CommonOptions.GetTargetResultOption);
command.Options.Add(CommonOptions.GetResultOutputFileOption);
command.Subcommands.Add(CleanFileBasedAppArtifactsCommandParser.Command);

command.SetAction(CleanCommand.Run);
Expand Down
9 changes: 8 additions & 1 deletion src/Cli/dotnet/Commands/CommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ internal static CommandBase CreateVirtualOrPhysicalCommand(
var forwardedArgs = parseResult.OptionValuesToBeForwarded(command);
if (nonBinLogArgs is [{ } arg] && VirtualProjectBuildingCommand.IsValidEntryPointPath(arg))
{
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([.. forwardedArgs, .. binLogArgs,], [.. optionsToUseWhenParsingMSBuildFlags]);
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([.. forwardedArgs, .. binLogArgs],
[
.. optionsToUseWhenParsingMSBuildFlags,
CommonOptions.GetPropertyOption,
CommonOptions.GetItemOption,
CommonOptions.GetTargetResultOption,
CommonOptions.GetResultOutputFileOption,
]);
return configureVirtualCommand(msbuildArgs, Path.GetFullPath(arg));
}
else
Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Pack/PackCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ private static Command ConstructCommand()
command.Options.Add(ConfigurationOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
command.Options.Add(TargetOption);
command.Options.Add(CommonOptions.GetPropertyOption);
command.Options.Add(CommonOptions.GetItemOption);
command.Options.Add(CommonOptions.GetTargetResultOption);
command.Options.Add(CommonOptions.GetResultOutputFileOption);

// Don't include runtime option because we want to include it specifically and allow the short version ("-r") to be used
RestoreCommandParser.AddImplicitRestoreOptions(command, includeRuntimeOption: false, includeNoDependenciesOption: true);
Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ private static Command ConstructCommand()
command.Options.Add(CommonOptions.OperatingSystemOption);
command.Options.Add(CommonOptions.DisableBuildServersOption);
command.Options.Add(TargetOption);
command.Options.Add(CommonOptions.GetPropertyOption);
command.Options.Add(CommonOptions.GetItemOption);
command.Options.Add(CommonOptions.GetTargetResultOption);
command.Options.Add(CommonOptions.GetResultOutputFileOption);

command.SetAction(PublishCommand.Run);

Expand Down
4 changes: 4 additions & 0 deletions src/Cli/dotnet/Commands/Restore/RestoreCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ private static Command ConstructCommand()

command.Options.Add(CommonOptions.ArchitectureOption);
command.Options.Add(CommonOptions.OperatingSystemOption);
command.Options.Add(CommonOptions.GetPropertyOption);
command.Options.Add(CommonOptions.GetItemOption);
command.Options.Add(CommonOptions.GetTargetResultOption);
command.Options.Add(CommonOptions.GetResultOutputFileOption);
command.SetAction(RestoreCommand.Run);

return command;
Expand Down
Loading
Loading