Skip to content

Commit adca5c6

Browse files
committed
Run to new style
1 parent 34ef3e3 commit adca5c6

File tree

5 files changed

+59
-35
lines changed

5 files changed

+59
-35
lines changed

src/ConsoleAppFramework/Command.cs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ public string BuildDelegateType(string delegateName)
144144
public record class CommandParameter
145145
{
146146
public required EquatableTypeSymbol Type { get; init; }
147-
public required Location Location { get; init; }
148-
public required WellKnownTypes WellKnownTypes { get; init; }
147+
public required IgnoreEquality<Location> Location { get; init; }
148+
public required IgnoreEquality<WellKnownTypes> WellKnownTypes { get; init; }
149149
public required bool IsNullableReference { get; init; }
150150
public required bool IsParams { get; init; }
151151
public required string Name { get; init; }
@@ -238,7 +238,7 @@ string Core(ITypeSymbol type, bool nullable)
238238
if (type.TypeKind == TypeKind.Array)
239239
{
240240
var elementType = (type as IArrayTypeSymbol)!.ElementType;
241-
var parsable = WellKnownTypes.ISpanParsable;
241+
var parsable = WellKnownTypes.Value.ISpanParsable;
242242
if (parsable != null) // has parsable
243243
{
244244
if (elementType.AllInterfaces.Any(x => x.EqualsUnconstructedGenericType(parsable)))
@@ -250,12 +250,12 @@ string Core(ITypeSymbol type, bool nullable)
250250
}
251251

252252
// System.DateTimeOffset, System.Guid, System.Version
253-
tryParseKnownPrimitive = WellKnownTypes.HasTryParse(type);
253+
tryParseKnownPrimitive = WellKnownTypes.Value.HasTryParse(type);
254254

255255
if (!tryParseKnownPrimitive)
256256
{
257257
// ISpanParsable<T> (BigInteger, Complex, Half, Int128, etc...)
258-
var parsable = WellKnownTypes.ISpanParsable;
258+
var parsable = WellKnownTypes.Value.ISpanParsable;
259259
if (parsable != null) // has parsable
260260
{
261261
tryParseIParsable = type.AllInterfaces.Any(x => x.EqualsUnconstructedGenericType(parsable));
@@ -312,13 +312,6 @@ public string DefaultValueToString(bool castValue = true, bool enumIncludeTypeNa
312312
return $"({Type.ToFullyQualifiedFormatDisplayString()}){DefaultValue}";
313313
}
314314

315-
public string? GetEnumSymbolName(object value)
316-
{
317-
var symbol = Type.GetMembers().OfType<IFieldSymbol>().FirstOrDefault(x => x.ConstantValue == value);
318-
if (symbol == null) return "";
319-
return symbol.Name;
320-
}
321-
322315
public string ToTypeDisplayString()
323316
{
324317
var t = Type.ToFullyQualifiedFormatDisplayString();

src/ConsoleAppFramework/ConsoleAppGenerator.cs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3636
}
3737

3838
return false;
39-
}, (context, ct) => new RunContext((InvocationExpressionSyntax)context.Node, context.SemanticModel))
39+
}, (context, ct) =>
40+
{
41+
var reporter = new DiagnosticReporter();
42+
var node = (InvocationExpressionSyntax)context.Node;
43+
var wellknownTypes = new WellKnownTypes(context.SemanticModel.Compilation);
44+
var parser = new Parser(reporter, node, context.SemanticModel, wellknownTypes, DelegateBuildType.MakeDelegateWhenHasDefaultValue, []);
45+
var isRunAsync = (node.Expression as MemberAccessExpressionSyntax)?.Name.Identifier.Text == "RunAsync";
46+
47+
var command = parser.ParseAndValidateForRun();
48+
return new CommandContext(command, isRunAsync, reporter, node);
49+
})
4050
.WithTrackingName("ConsoleApp.Run.0_CreateSyntaxProvider"); // annotate for IncrementalGeneratorTest
4151

4252
context.RegisterSourceOutput(runSource, EmitConsoleAppRun);
@@ -561,36 +571,29 @@ namespace ConsoleAppFramework;
561571
562572
""";
563573

564-
static void EmitConsoleAppRun(SourceProductionContext sourceProductionContext, RunContext runNode)
574+
static void EmitConsoleAppRun(SourceProductionContext sourceProductionContext, CommandContext commandContext)
565575
{
566-
var node = runNode.Node;
567-
var model = runNode.SemanticModel;
568-
569-
var wellKnownTypes = new WellKnownTypes(model.Compilation);
570-
571-
var reporter = new DiagnosticReporter();
572-
var parser = new Parser(reporter, node, model, wellKnownTypes, DelegateBuildType.MakeDelegateWhenHasDefaultValue, []);
573-
var command = parser.ParseAndValidateForRun();
574-
if (command == null)
576+
if (commandContext.DiagnosticReporter.HasDiagnostics)
575577
{
576-
reporter.ReportToContext(sourceProductionContext);
578+
commandContext.DiagnosticReporter.ReportToContext(sourceProductionContext);
577579
return;
578580
}
581+
var command = commandContext.Command;
582+
if (command == null) return;
583+
579584
if (command.HasFilter)
580585
{
581-
sourceProductionContext.ReportDiagnostic(DiagnosticDescriptors.CommandHasFilter, node.GetLocation());
586+
sourceProductionContext.ReportDiagnostic(DiagnosticDescriptors.CommandHasFilter, commandContext.Node.GetLocation());
582587
return;
583588
}
584589

585-
var isRunAsync = ((node.Expression as MemberAccessExpressionSyntax)?.Name.Identifier.Text == "RunAsync");
586-
587590
var sb = new SourceBuilder(0);
588591
sb.AppendLine(GeneratedCodeHeader);
589592
using (sb.BeginBlock("internal static partial class ConsoleApp"))
590593
{
591594
var emitter = new Emitter();
592595
var withId = new Emitter.CommandWithId(null, command, -1);
593-
emitter.EmitRun(sb, withId, isRunAsync);
596+
emitter.EmitRun(sb, withId, command.IsAsync);
594597
}
595598
sourceProductionContext.AddSource("ConsoleApp.Run.g.cs", sb.ToString());
596599

@@ -756,19 +759,20 @@ static void EmitConsoleAppBuilder(SourceProductionContext sourceProductionContex
756759
sourceProductionContext.AddSource("ConsoleApp.Builder.Help.g.cs", help.ToString());
757760
}
758761

759-
class CommandContext(Command command, bool isAsync, DiagnosticReporter diagnosticReporter) : IEquatable<CommandContext>
762+
class CommandContext(Command? command, bool isAsync, DiagnosticReporter diagnosticReporter, InvocationExpressionSyntax node) : IEquatable<CommandContext>
760763
{
761-
public Command Command => command;
764+
public Command? Command => command;
762765
public DiagnosticReporter DiagnosticReporter => diagnosticReporter;
766+
public InvocationExpressionSyntax Node => node;
763767
public bool IsAsync => isAsync;
764768

765769
public bool Equals(CommandContext other)
766770
{
767771
// has diagnostics, always go to modified(don't cache)
768772
if (diagnosticReporter.HasDiagnostics || other.DiagnosticReporter.HasDiagnostics) return false;
773+
if (command == null || other.Command == null) return false; // maybe has diagnostics
769774

770775
if (isAsync != other.IsAsync) return false;
771-
772776
return command.Equals(other.Command);
773777
}
774778
}

src/ConsoleAppFramework/EquatableTypeSymbol.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,24 @@ namespace ConsoleAppFramework;
55

66
public class EquatableTypeSymbol(ITypeSymbol typeSymbol) : IEquatable<EquatableTypeSymbol>
77
{
8-
// check this two types usage for Equality
8+
// Used for build argument parser, maybe ok to equals name.
99
public ITypeSymbol TypeSymbol => typeSymbol;
10+
11+
// GetMembers is called for Enum and fields is not condition for command equality.
1012
public ImmutableArray<ISymbol> GetMembers() => typeSymbol.GetMembers();
1113

1214
public TypeKind TypeKind { get; } = typeSymbol.TypeKind;
1315
public SpecialType SpecialType { get; } = typeSymbol.SpecialType;
1416

15-
1617
public string ToFullyQualifiedFormatDisplayString() => typeSymbol.ToFullyQualifiedFormatDisplayString();
1718
public string ToDisplayString(NullableFlowState state, SymbolDisplayFormat format) => typeSymbol.ToDisplayString(state, format);
1819

1920
public bool Equals(EquatableTypeSymbol other)
2021
{
21-
// TODO:
22-
return false;
22+
if (this.TypeKind != other.TypeKind) return false;
23+
if (this.SpecialType != other.SpecialType) return false;
24+
if (this.TypeSymbol.Name != other.TypeSymbol.Name) return false;
25+
26+
return this.TypeSymbol.EqualsNamespaceAndName(other.TypeSymbol);
2327
}
2428
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace ConsoleAppFramework;
2+
3+
public readonly struct IgnoreEquality<T>(T value) : IEquatable<IgnoreEquality<T>>
4+
{
5+
public readonly T Value => value;
6+
7+
public static implicit operator IgnoreEquality<T>(T value)
8+
{
9+
return new IgnoreEquality<T>(value);
10+
}
11+
12+
public static implicit operator T(IgnoreEquality<T> value)
13+
{
14+
return value.Value;
15+
}
16+
17+
public bool Equals(IgnoreEquality<T> other)
18+
{
19+
// always true to ignore equality check.
20+
return true;
21+
}
22+
}

tests/ConsoleAppFramework.GeneratorTests/IncrementalGeneratorTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public void RunLambda()
5454
reasons[2][0].Reasons.Should().Be("Modified");
5555

5656
VerifySourceOutputReasonIsCached(reasons[1]);
57+
VerifySourceOutputReasonIsNotCached(reasons[2]);
5758
}
5859

5960
[Fact]

0 commit comments

Comments
 (0)