-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from poizan42/inject-parent-commands
Proposal for fix for #14 by adding support for injecting parent commands as properties.
- Loading branch information
Showing
86 changed files
with
1,691 additions
and
547 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
src/DotMake.CommandLine.SourceGeneration/CliParentCommandRefInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using Microsoft.CodeAnalysis; | ||
|
||
namespace DotMake.CommandLine.SourceGeneration | ||
{ | ||
public class CliParentCommandRefInfo : CliSymbolInfo, IEquatable<CliParentCommandRefInfo> | ||
{ | ||
public const string DiagnosticName = "CLI parent command reference"; | ||
|
||
public CliParentCommandRefInfo(IPropertySymbol symbol, SyntaxNode syntaxNode, SemanticModel semanticModel, | ||
int parentTreeIndex, CliCommandSettings parentCommandSettings) : base(symbol, syntaxNode, semanticModel) | ||
{ | ||
ParentTreeIndex = parentTreeIndex; | ||
ParentCommandSettings = parentCommandSettings; | ||
|
||
Analyze(); | ||
|
||
if (HasProblem) | ||
return; | ||
} | ||
|
||
public int ParentTreeIndex { get; } | ||
public CliCommandSettings ParentCommandSettings { get; } | ||
public new IPropertySymbol Symbol => (IPropertySymbol)base.Symbol; | ||
|
||
private void Analyze() | ||
{ | ||
if ((Symbol.DeclaredAccessibility != Accessibility.Public && Symbol.DeclaredAccessibility != Accessibility.Internal) | ||
|| Symbol.IsStatic) | ||
AddDiagnostic(DiagnosticDescriptors.WarningPropertyNotPublicNonStatic, DiagnosticName); | ||
else | ||
{ | ||
if (Symbol.GetMethod == null | ||
|| (Symbol.GetMethod.DeclaredAccessibility != Accessibility.Public && Symbol.GetMethod.DeclaredAccessibility != Accessibility.Internal)) | ||
AddDiagnostic(DiagnosticDescriptors.ErrorPropertyHasNotPublicGetter, DiagnosticName); | ||
|
||
if (Symbol.SetMethod == null | ||
|| (Symbol.SetMethod.DeclaredAccessibility != Accessibility.Public && Symbol.SetMethod.DeclaredAccessibility != Accessibility.Internal)) | ||
AddDiagnostic(DiagnosticDescriptors.ErrorPropertyHasNotPublicSetter, DiagnosticName); | ||
} | ||
} | ||
|
||
public bool Equals(CliParentCommandRefInfo other) | ||
{ | ||
return base.Equals(other); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.CommandLine; | ||
|
||
namespace DotMake.CommandLine | ||
{ | ||
/// <summary> | ||
/// Context used during binding of commands | ||
/// </summary> | ||
public class CliBindContext | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CliBindContext" /> class. | ||
/// </summary> | ||
/// <param name="parseResult">A parse result describing the outcome of the parse operation.</param> | ||
public CliBindContext(ParseResult parseResult) | ||
{ | ||
ParseResult = parseResult; | ||
} | ||
|
||
/// <summary>A parse result describing the outcome of the parse operation.</summary> | ||
public ParseResult ParseResult { get; } | ||
|
||
/// <summary> | ||
/// Creates a new instance of the definition class and binds/populates the properties from the parse result, | ||
/// or returns a cached instance of the definition class earlier returned from either BindOrGetBindResult() overload. | ||
/// </summary> | ||
/// <typeparam name="TDefinition">The definition class.</typeparam> | ||
/// <returns></returns> | ||
public TDefinition BindOrGetBindResult<TDefinition>() => (TDefinition)BindOrGetBindResult(typeof(TDefinition)); | ||
|
||
/// <summary> | ||
/// Creates a new instance of the definition class and binds/populates the properties from the parse result, | ||
/// or returns a cached instance of the definition class earlier returned from either BindOrGetBindResult() overload. | ||
/// </summary> | ||
/// <param name="commandDefinitionType">The type of the definition class.</param> | ||
/// <returns>An instance of the definition class whose properties were bound/populated from the parse result.</returns> | ||
public object BindOrGetBindResult(Type commandDefinitionType) | ||
{ | ||
if (bindResults.TryGetValue(commandDefinitionType, out object bindResult)) | ||
{ | ||
return bindResult; | ||
} | ||
var commandBuilder = CliCommandBuilder.Get(commandDefinitionType); | ||
object commandObj = commandBuilder.Bind(this); | ||
bindResults[commandDefinitionType] = commandObj; | ||
return commandObj; | ||
} | ||
|
||
private readonly Dictionary<Type, object> bindResults = new(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/TestApp/Commands/RootWithNestedChildrenReferencingRootCliCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#pragma warning disable CS1591 | ||
#pragma warning disable CA1822 // Mark members as static | ||
using System; | ||
using DotMake.CommandLine; | ||
|
||
namespace TestApp.Commands | ||
{ | ||
#region RootWithNestedChildrenReferencingRootCliCommand | ||
|
||
// Sub-commands can get a reference to the parent command by adding a property of the parent command type. | ||
|
||
[CliCommand(Description = "A root cli command with nested children")] | ||
public class RootWithNestedChildrenReferencingRootCliCommand | ||
{ | ||
[CliOption(Description = "This is a global option (Recursive option on the root command), it can appear anywhere on the command line", | ||
Recursive = true)] | ||
public string GlobalOption1 { get; set; } = "DefaultForGlobalOption1"; | ||
|
||
[CliArgument(Description = "Description for RootArgument1")] | ||
public string RootArgument1 { get; set; } | ||
|
||
public void Run(CliContext context) | ||
{ | ||
context.ShowValues(); | ||
} | ||
|
||
[CliCommand(Description = "A nested level 1 sub-command which accesses the root command")] | ||
public class Level1SubCliCommand | ||
{ | ||
[CliOption(Description = "This is global for all sub commands (it can appear anywhere after the level-1 verb)", | ||
Recursive = true)] | ||
public string Level1RecursiveOption1 { get; set; } = "DefaultForLevel1RecusiveOption1"; | ||
|
||
[CliArgument(Description = "Description for Argument1")] | ||
public string Argument1 { get; set; } | ||
|
||
// The parent command gets automatically injected | ||
public RootWithNestedChildrenReferencingRootCliCommand RootCommand { get; set; } | ||
|
||
public void Run(CliContext context) | ||
{ | ||
context.ShowValues(); | ||
} | ||
|
||
[CliCommand(Description = "A nested level 2 sub-command which accesses its parent commands")] | ||
public class Level2SubCliCommand | ||
{ | ||
[CliOption(Description = "Description for Option1")] | ||
public string Option1 { get; set; } = "DefaultForOption1"; | ||
|
||
[CliArgument(Description = "Description for Argument1")] | ||
public string Argument1 { get; set; } | ||
|
||
// All ancestor commands gets injected | ||
public RootWithNestedChildrenReferencingRootCliCommand RootCommand { get; set; } | ||
public Level1SubCliCommand ParentCommand { get; set; } | ||
|
||
public void Run(CliContext context) | ||
{ | ||
context.ShowValues(); | ||
Console.WriteLine($"Level1RecursiveOption1 = {ParentCommand.Level1RecursiveOption1}"); | ||
Console.WriteLine($"parent Argument1 = {ParentCommand.Argument1}"); | ||
Console.WriteLine($"GlobalOption1 = {RootCommand.GlobalOption1}"); | ||
Console.WriteLine($"RootArgument1 = {RootCommand.RootArgument1}"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
#endregion | ||
} |
4 changes: 2 additions & 2 deletions
4
...otMake.CommandLine.SourceGeneration.CliCommandGenerator/(ModuleInitializerAttribute).g.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...n/DotMake.CommandLine.SourceGeneration.CliCommandGenerator/(RequiredMemberAttribute).g.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.