Skip to content

Commit aa28b0b

Browse files
committed
WIP GlobalOption help
1 parent 29d9d92 commit aa28b0b

File tree

4 files changed

+106
-3
lines changed

4 files changed

+106
-3
lines changed

sandbox/GeneratorSandbox/Program.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
// Enum.TryParse<Fruit>("", true,
1919
// parse immediately
2020

21-
var f = app.AddGlobalOption<Fruit>(ref args, "-f");
21+
var f = app.AddGlobalOption<Fruit>(ref args, "-f", "", defaultValue: Fruit.Apple);
2222

2323

2424

25-
var verbose = app.AddGlobalOption<bool>(ref args, "-v|--verbose");
25+
26+
var verbose = app.AddGlobalOption<bool>(ref args, $"takoyaki", description: "", defaultValue: true, );
2627
var noColor = app.AddGlobalOption<bool>(ref args, "--no-color", "Don't colorize output.");
2728
var dryRun = app.AddGlobalOption<bool>(ref args, "--dry-run");
2829
var prefixOutput = app.AddRequiredGlobalOption<string>(ref args, "--prefix-output|-pp|-po", "Prefix output with level.");

src/ConsoleAppFramework/Command.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,3 +461,22 @@ public string BuildNew(string nextFilterName)
461461
return $"new {TypeFullName}({string.Join(", ", p)})";
462462
}
463463
}
464+
465+
public record class GlobalOptionInfo
466+
{
467+
public required EquatableTypeSymbol Type { get; init; }
468+
public required bool IsRequired { get; init; }
469+
public required string Name { get; init; }
470+
public required string Description { get; init; }
471+
public required object? DefaultValue { get; init; }
472+
473+
public CommandParameter ToDummyCommandParameter()
474+
{
475+
//return new CommandParameter
476+
{
477+
/// DefaultValue
478+
}
479+
480+
throw new NotImplementedException();
481+
}
482+
}

src/ConsoleAppFramework/ConsoleAppGenerator.cs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44
using System.Collections.Immutable;
55
using System.ComponentModel.Design;
6+
using System.Linq.Expressions;
67
using System.Reflection;
8+
using System.Runtime.CompilerServices;
79

810
namespace ConsoleAppFramework;
911

@@ -136,7 +138,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
136138

137139
var expr = invocationExpression.Expression as MemberAccessExpressionSyntax;
138140
var methodName = expr?.Name.Identifier.Text;
139-
if (methodName is "Add" or "UseFilter" or "Run" or "RunAsync")
141+
if (methodName is "Add" or "UseFilter" or "Run" or "RunAsync" or "AddGlobalOption" or "AddRequiredGlobalOption")
140142
{
141143
return true;
142144
}
@@ -292,6 +294,8 @@ static void EmitConsoleAppBuilder(SourceProductionContext sourceProductionContex
292294
using (help.BeginBlock("internal static partial class ConsoleApp"))
293295
using (help.BeginBlock("internal partial class ConsoleAppBuilder"))
294296
{
297+
// TODO: collectBuilderContext.GlobalOptions
298+
295299
var emitter = new Emitter();
296300
emitter.EmitHelp(help, commandIds!);
297301
}
@@ -369,6 +373,8 @@ class CollectBuilderContext : IEquatable<CollectBuilderContext>
369373
FilterInfo[]? globalFilters { get; }
370374
ConsoleAppFrameworkGeneratorOptions generatorOptions { get; }
371375

376+
public GlobalOptionInfo[] GlobalOptions { get; } = [];
377+
372378
public CollectBuilderContext(ConsoleAppFrameworkGeneratorOptions generatorOptions, ImmutableArray<(BuilderContext, string?, SymbolKind?)> contexts, CancellationToken cancellationToken)
373379
{
374380
this.DiagnosticReporter = new DiagnosticReporter();
@@ -475,6 +481,82 @@ public CollectBuilderContext(ConsoleAppFrameworkGeneratorOptions generatorOption
475481
return commands;
476482
});
477483

484+
GlobalOptions = methodGroup["AddGlobalOption"].Select(x => (context: x.Item1, required: false))
485+
.Concat(methodGroup["AddRequiredGlobalOption"].Select(x => (context: x.Item1, required: true)))
486+
.Select(x =>
487+
{
488+
var node = x.context.Node;
489+
var model = x.context.Model;
490+
491+
EquatableTypeSymbol typeSymbol = default!;
492+
string name = "";
493+
string description = "";
494+
bool isRequired = x.required;
495+
object? defaultValue = null;
496+
497+
if (node.Expression is MemberAccessExpressionSyntax memberAccess && memberAccess.Name is GenericNameSyntax genericName)
498+
{
499+
var typeArgument = genericName.TypeArgumentList.Arguments[0];
500+
typeSymbol = new(model.GetTypeInfo(typeArgument).Type!); // TODO: not !
501+
}
502+
503+
var arguments = node.ArgumentList.Arguments;
504+
if (arguments.Count >= 2) // string name
505+
{
506+
var constant = model.GetConstantValue(arguments[1].Expression); // TODO: check
507+
name = constant.Value!.ToString();
508+
}
509+
510+
511+
// TODO: use named argument???
512+
513+
if (arguments.Count >= 3) // string description = ""
514+
{
515+
// is defaultValue???
516+
517+
518+
var constant = model.GetConstantValue(arguments[2].Expression);
519+
description = constant.Value!.ToString();
520+
}
521+
522+
if (!isRequired)
523+
{
524+
if (arguments.Count >= 4) // T defaultValue = default(T)
525+
{
526+
var constant = model.GetConstantValue(arguments[3].Expression);
527+
defaultValue = constant.Value!;
528+
}
529+
else
530+
{
531+
// set defaultValue from
532+
var symbol = model.GetSymbolInfo(node).Symbol;
533+
if (symbol is IMethodSymbol methodSymbol)
534+
{
535+
var parameter = methodSymbol.Parameters[3];
536+
if (parameter.HasExplicitDefaultValue)
537+
{
538+
defaultValue = parameter.ExplicitDefaultValue;
539+
}
540+
else
541+
{
542+
543+
}
544+
}
545+
}
546+
}
547+
548+
return new GlobalOptionInfo
549+
{
550+
Type = typeSymbol,
551+
IsRequired = isRequired,
552+
Name = name,
553+
Description = description,
554+
DefaultValue = defaultValue
555+
};
556+
})
557+
.Where(x => x != null)
558+
.ToArray();
559+
478560
if (DiagnosticReporter.HasDiagnostics)
479561
{
480562
return;

src/ConsoleAppFramework/Emitter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ public void EmitHelp(SourceBuilder sb, Command command)
646646
}
647647
}
648648

649+
// for multiple commands(Builder)
649650
public void EmitHelp(SourceBuilder sb, CommandWithId[] commands)
650651
{
651652
using (sb.BeginBlock("static partial void ShowHelp(int helpId)"))

0 commit comments

Comments
 (0)