Skip to content

Commit 7fb96d2

Browse files
committed
NewCommand
1 parent 4c98d92 commit 7fb96d2

34 files changed

+266
-294
lines changed

src/Cli/Microsoft.TemplateEngine.Cli/Commands/BaseCommand.cs

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.CommandLine;
55
using System.CommandLine.Completions;
66
using System.CommandLine.Invocation;
7+
using System.Diagnostics;
78
using System.Reflection;
89
using Microsoft.DotNet.Cli.Utils;
910
using Microsoft.DotNet.Cli.Utils.Extensions;
@@ -17,18 +18,9 @@
1718

1819
namespace Microsoft.TemplateEngine.Cli.Commands
1920
{
20-
internal abstract class BaseCommand : Command
21+
internal abstract class BaseCommand(string name, string description) : Command(name, description)
2122
{
22-
private readonly Func<ParseResult, ITemplateEngineHost> _hostBuilder;
23-
24-
protected BaseCommand(
25-
Func<ParseResult, ITemplateEngineHost> hostBuilder,
26-
string name,
27-
string description)
28-
: base(name, description)
29-
{
30-
_hostBuilder = hostBuilder;
31-
}
23+
public abstract void SetAction(Func<ParseResult, ITemplateEngineHost> hostBuilder);
3224

3325
protected internal virtual IEnumerable<CompletionItem> GetCompletions(CompletionContext context, IEngineEnvironmentSettings environmentSettings, TemplatePackageManager templatePackageManager)
3426
{
@@ -37,9 +29,8 @@ protected internal virtual IEnumerable<CompletionItem> GetCompletions(Completion
3729
#pragma warning restore SA1100 // Do not prefix calls with base unless local implementation exists
3830
}
3931

40-
protected IEngineEnvironmentSettings CreateEnvironmentSettings(GlobalArgs args, ParseResult parseResult)
32+
protected static IEngineEnvironmentSettings CreateEnvironmentSettings(GlobalArgs args, ITemplateEngineHost host)
4133
{
42-
ITemplateEngineHost host = _hostBuilder(parseResult);
4334
IEnvironment environment = new CliEnvironment();
4435

4536
return new EngineEnvironmentSettings(
@@ -50,15 +41,12 @@ protected IEngineEnvironmentSettings CreateEnvironmentSettings(GlobalArgs args,
5041
}
5142
}
5243

53-
internal abstract class BaseCommand<TArgs> : BaseCommand where TArgs : GlobalArgs
44+
internal abstract class BaseCommand<TArgs>(string name, string description) : BaseCommand(name, description) where TArgs : GlobalArgs
5445
{
55-
internal BaseCommand(
56-
Func<ParseResult, ITemplateEngineHost> hostBuilder,
57-
string name,
58-
string description)
59-
: base(hostBuilder, name, description)
46+
public override void SetAction(Func<ParseResult, ITemplateEngineHost> hostBuilder)
6047
{
61-
Action = new CommandAction(this);
48+
Debug.Assert(Action == null);
49+
Action = new CommandAction(this, hostBuilder);
6250
}
6351

6452
public override IEnumerable<CompletionItem> GetCompletions(CompletionContext context)
@@ -67,8 +55,9 @@ public override IEnumerable<CompletionItem> GetCompletions(CompletionContext con
6755
{
6856
return base.GetCompletions(context);
6957
}
58+
7059
GlobalArgs args = new(this, context.ParseResult);
71-
using IEngineEnvironmentSettings environmentSettings = CreateEnvironmentSettings(args, context.ParseResult);
60+
using IEngineEnvironmentSettings environmentSettings = CreateEnvironmentSettings(args, GetHost(context.ParseResult));
7261
using TemplatePackageManager templatePackageManager = new(environmentSettings);
7362
return GetCompletions(context, environmentSettings, templatePackageManager).ToList();
7463
}
@@ -118,6 +107,12 @@ protected static void PrintDeprecationMessage<TDepr, TNew>(ParseResult parseResu
118107
Reporter.Output.WriteLine();
119108
}
120109

110+
protected ITemplateEngineHost GetHost(ParseResult parseResult)
111+
{
112+
var action = (CommandAction)(Action ?? throw new InvalidOperationException("Command action not set"));
113+
return action.HostBuilder(parseResult);
114+
}
115+
121116
protected abstract Task<NewCommandStatus> ExecuteAsync(TArgs args, IEngineEnvironmentSettings environmentSettings, TemplatePackageManager templatePackageManager, ParseResult parseResult, CancellationToken cancellationToken);
122117

123118
protected abstract TArgs ParseContext(ParseResult parseResult);
@@ -222,16 +217,15 @@ private static void HandleDebugShowConfig(TArgs args, IEngineEnvironmentSettings
222217
Reporter.Output.WriteLine();
223218
}
224219

225-
private sealed class CommandAction : AsynchronousCommandLineAction
220+
private sealed class CommandAction(BaseCommand<TArgs> command, Func<ParseResult, ITemplateEngineHost> hostBuilder) : AsynchronousCommandLineAction
226221
{
227-
private readonly BaseCommand<TArgs> _command;
228-
229-
public CommandAction(BaseCommand<TArgs> command) => _command = command;
222+
public Func<ParseResult, ITemplateEngineHost> HostBuilder => hostBuilder;
230223

231224
public override async Task<int> InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
232225
{
233-
TArgs args = _command.ParseContext(parseResult);
234-
using IEngineEnvironmentSettings environmentSettings = _command.CreateEnvironmentSettings(args, parseResult);
226+
TArgs args = command.ParseContext(parseResult);
227+
228+
using IEngineEnvironmentSettings environmentSettings = CreateEnvironmentSettings(args, hostBuilder(parseResult));
235229
using TemplatePackageManager templatePackageManager = new(environmentSettings);
236230

237231
NewCommandStatus returnCode;
@@ -241,7 +235,7 @@ public override async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
241235
using (Timing.Over(environmentSettings.Host.Logger, "Execute"))
242236
{
243237
await HandleGlobalOptionsAsync(args, environmentSettings, templatePackageManager, cancellationToken).ConfigureAwait(false);
244-
returnCode = await _command.ExecuteAsync(args, environmentSettings, templatePackageManager, parseResult, cancellationToken).ConfigureAwait(false);
238+
returnCode = await command.ExecuteAsync(args, environmentSettings, templatePackageManager, parseResult, cancellationToken).ConfigureAwait(false);
245239
}
246240
}
247241
catch (Exception ex)

src/Cli/Microsoft.TemplateEngine.Cli/Commands/NewCommand.Help.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public IEnumerable<Action<HelpContext>> CustomHelpLayout()
1717
throw new ArgumentException($"{nameof(context)} should be for {nameof(NewCommand)}");
1818
}
1919
NewCommandArgs args = new(newCommand, context.ParseResult);
20-
using IEngineEnvironmentSettings environmentSettings = CreateEnvironmentSettings(args, context.ParseResult);
20+
using IEngineEnvironmentSettings environmentSettings = CreateEnvironmentSettings(args, GetHost(context.ParseResult));
2121
InstantiateCommandArgs instantiateCommandArgs = InstantiateCommandArgs.FromNewCommandArgs(args);
2222
InstantiateCommand.WriteHelp(context, instantiateCommandArgs, environmentSettings);
2323
};

src/Cli/Microsoft.TemplateEngine.Cli/Commands/NewCommand.Legacy.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.CommandLine;
55
using System.CommandLine.Parsing;
6-
using Microsoft.TemplateEngine.Abstractions;
76

87
namespace Microsoft.TemplateEngine.Cli.Commands
98
{
@@ -133,7 +132,7 @@ private static void ValidateArgumentUsage(CommandResult commandResult, params Ar
133132
}
134133
}
135134

136-
private void BuildLegacySymbols(Func<ParseResult, ITemplateEngineHost> hostBuilder)
135+
private void BuildLegacySymbols()
137136
{
138137
Arguments.Add(ShortNameArgument);
139138
Arguments.Add(RemainingArguments);
@@ -154,14 +153,14 @@ private void BuildLegacySymbols(Func<ParseResult, ITemplateEngineHost> hostBuild
154153

155154
TreatUnmatchedTokensAsErrors = true;
156155

157-
Add(new LegacyInstallCommand(this, hostBuilder));
158-
Add(new LegacyUninstallCommand(this, hostBuilder));
159-
Add(new LegacyUpdateCheckCommand(this, hostBuilder));
160-
Add(new LegacyUpdateApplyCommand(this, hostBuilder));
161-
Add(new LegacySearchCommand(this, hostBuilder));
162-
Add(new LegacyListCommand(this, hostBuilder));
163-
Add(new LegacyAliasAddCommand(hostBuilder));
164-
Add(new LegacyAliasShowCommand(hostBuilder));
156+
Add(new LegacyInstallCommand(this));
157+
Add(new LegacyUninstallCommand(this));
158+
Add(new LegacyUpdateCheckCommand(this));
159+
Add(new LegacyUpdateApplyCommand(this));
160+
Add(new LegacySearchCommand(this));
161+
Add(new LegacyListCommand(this));
162+
Add(new LegacyAliasAddCommand());
163+
Add(new LegacyAliasShowCommand());
165164
}
166165
}
167166
}

src/Cli/Microsoft.TemplateEngine.Cli/Commands/NewCommand.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,22 @@ namespace Microsoft.TemplateEngine.Cli.Commands
1010
{
1111
internal partial class NewCommand : BaseCommand<NewCommandArgs>, ICustomHelp, ICommandDocument
1212
{
13-
internal NewCommand(
14-
string commandName,
15-
Func<ParseResult, ITemplateEngineHost> hostBuilder)
16-
: base(hostBuilder, commandName, SymbolStrings.Command_New_Description)
13+
internal NewCommand(string commandName)
14+
: base(commandName, SymbolStrings.Command_New_Description)
1715
{
1816
TreatUnmatchedTokensAsErrors = true;
1917

2018
//it is important that legacy commands are built before non-legacy, as non legacy commands are building validators that rely on legacy stuff
21-
BuildLegacySymbols(hostBuilder);
19+
BuildLegacySymbols();
2220

23-
Add(new InstantiateCommand(this, hostBuilder));
24-
Add(new InstallCommand(this, hostBuilder));
25-
Add(new UninstallCommand(this, hostBuilder));
26-
Add(new UpdateCommand(this, hostBuilder));
27-
Add(new SearchCommand(this, hostBuilder));
28-
Add(new ListCommand(this, hostBuilder));
29-
Add(new AliasCommand(hostBuilder));
30-
Add(new DetailsCommand(hostBuilder));
21+
Add(new InstantiateCommand(this));
22+
Add(new InstallCommand(this));
23+
Add(new UninstallCommand(this));
24+
Add(new UpdateCommand(this));
25+
Add(new SearchCommand(this));
26+
Add(new ListCommand(this));
27+
Add(new AliasCommand());
28+
Add(new DetailsCommand());
3129

3230
Options.Add(DebugCustomSettingsLocationOption);
3331
Options.Add(DebugVirtualizeSettingsOption);
@@ -110,6 +108,16 @@ internal NewCommand(
110108
SharedOptions.NoUpdateCheckOption
111109
};
112110

111+
public override void SetAction(Func<ParseResult, ITemplateEngineHost> hostBuilder)
112+
{
113+
base.SetAction(hostBuilder);
114+
115+
foreach (BaseCommand command in Subcommands)
116+
{
117+
command.SetAction(hostBuilder);
118+
}
119+
}
120+
113121
protected internal override IEnumerable<CompletionItem> GetCompletions(CompletionContext context, IEngineEnvironmentSettings environmentSettings, TemplatePackageManager templatePackageManager)
114122
{
115123
if (context is not TextCompletionContext textCompletionContext)

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/AliasAddCommand.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.CommandLine;
5-
using Microsoft.TemplateEngine.Abstractions;
6-
74
namespace Microsoft.TemplateEngine.Cli.Commands
85
{
96
internal class AliasAddCommand : BaseAliasAddCommand
107
{
11-
internal AliasAddCommand(
12-
Func<ParseResult, ITemplateEngineHost> hostBuilder)
13-
: base(hostBuilder, "add")
8+
internal AliasAddCommand()
9+
: base("add")
1410
{
1511
Hidden = true;
1612
}

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/AliasCommand.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ namespace Microsoft.TemplateEngine.Cli.Commands
99
{
1010
internal class AliasCommand : BaseCommand<AliasCommandArgs>
1111
{
12-
internal AliasCommand(
13-
Func<ParseResult, ITemplateEngineHost> hostBuilder)
14-
: base(hostBuilder, "alias", SymbolStrings.Command_Alias_Description)
12+
internal AliasCommand()
13+
: base("alias", SymbolStrings.Command_Alias_Description)
1514
{
1615
Hidden = true;
17-
Add(new AliasAddCommand(hostBuilder));
18-
Add(new AliasShowCommand(hostBuilder));
16+
Add(new AliasAddCommand());
17+
Add(new AliasShowCommand());
1918
}
2019

2120
protected override Task<NewCommandStatus> ExecuteAsync(

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/AliasShowCommand.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.CommandLine;
5-
using Microsoft.TemplateEngine.Abstractions;
6-
74
namespace Microsoft.TemplateEngine.Cli.Commands
85
{
96
internal class AliasShowCommand : BaseAliasShowCommand
107
{
11-
internal AliasShowCommand(
12-
Func<ParseResult, ITemplateEngineHost> hostBuilder)
13-
: base(hostBuilder, "show")
8+
internal AliasShowCommand()
9+
: base("show")
1410
{
1511
Hidden = true;
1612
}

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/BaseAliasAddCommand.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ namespace Microsoft.TemplateEngine.Cli.Commands
99
{
1010
internal class BaseAliasAddCommand : BaseCommand<AliasAddCommandArgs>
1111
{
12-
internal BaseAliasAddCommand(
13-
Func<ParseResult, ITemplateEngineHost> hostBuilder,
14-
string commandName)
15-
: base(hostBuilder, commandName, SymbolStrings.Command_AliasAdd_Description) { }
12+
internal BaseAliasAddCommand(string commandName)
13+
: base(commandName, SymbolStrings.Command_AliasAdd_Description) { }
1614

1715
protected override Task<NewCommandStatus> ExecuteAsync(
1816
AliasAddCommandArgs args,

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/BaseAliasShowCommand.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ namespace Microsoft.TemplateEngine.Cli.Commands
99
{
1010
internal class BaseAliasShowCommand : BaseCommand<AliasShowCommandArgs>
1111
{
12-
internal BaseAliasShowCommand(
13-
Func<ParseResult, ITemplateEngineHost> hostBuilder,
14-
string commandName)
15-
: base(hostBuilder, commandName, SymbolStrings.Command_AliasShow_Description) { }
12+
internal BaseAliasShowCommand(string commandName)
13+
: base(commandName, SymbolStrings.Command_AliasShow_Description) { }
1614

1715
protected override Task<NewCommandStatus> ExecuteAsync(
1816
AliasShowCommandArgs args,

src/Cli/Microsoft.TemplateEngine.Cli/Commands/alias/LegacyAliasAddCommand.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.CommandLine;
5-
using Microsoft.TemplateEngine.Abstractions;
6-
74
namespace Microsoft.TemplateEngine.Cli.Commands
85
{
96
internal class LegacyAliasAddCommand : BaseAliasAddCommand
107
{
11-
internal LegacyAliasAddCommand(
12-
Func<ParseResult, ITemplateEngineHost> hostBuilder)
13-
: base(hostBuilder, "--alias")
8+
internal LegacyAliasAddCommand()
9+
: base("--alias")
1410
{
1511
Aliases.Add("-a");
1612
Hidden = true;

0 commit comments

Comments
 (0)