diff --git a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/GreenNode.Debug.g.cs b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/GreenNode.Debug.g.cs index 8a19256..e43875d 100644 --- a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/GreenNode.Debug.g.cs +++ b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/GreenNode.Debug.g.cs @@ -21,7 +21,7 @@ // Children: // global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample (Name = identifier, IsOptional = False, PassToBase = False) // global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample (Name = firstArg, IsOptional = False, PassToBase = False) -// global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample (Name = secondArg, IsOptional = True, PassToBase = False) +// global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample? (Name = secondArg, IsOptional = True, PassToBase = False) // ExtraData: // global::Tsu.Trees.RedGreen.Sample.SampleKind (Name = _kind, IsOptional = False, PassToBase = True) // global::Tsu.Trees.RedGreen.Sample.Internal.BinaryOperationExpressionSample diff --git a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs index e1f2c31..7404030 100644 --- a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs +++ b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen.SourceGenerator/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs @@ -37,7 +37,7 @@ public int SlotCount public global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode GetRequiredSlot(int index) { var node = this.GetSlot(index); - Debug.Assert((object)node != null) + Debug.Assert(node != null); return node!; } @@ -191,7 +191,7 @@ internal BinaryOperationExpressionSample(global::Tsu.Trees.RedGreen.Sample.Sampl partial class FunctionCallExpressionSample : global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample { - internal FunctionCallExpressionSample(global::Tsu.Trees.RedGreen.Sample.SampleKind kind, global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample secondArg) : base(kind) + internal FunctionCallExpressionSample(global::Tsu.Trees.RedGreen.Sample.SampleKind kind, global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample? secondArg) : base(kind) { this.SlotCount = 3; this.identifier = identifier; @@ -201,7 +201,7 @@ internal FunctionCallExpressionSample(global::Tsu.Trees.RedGreen.Sample.SampleKi public global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample Identifier => this.identifier; public global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample FirstArg => this.firstArg; - public global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample SecondArg => this.secondArg; + public global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample? SecondArg => this.secondArg; public override global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode? GetSlot(int index) => index switch @@ -215,7 +215,7 @@ internal FunctionCallExpressionSample(global::Tsu.Trees.RedGreen.Sample.SampleKi public override global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed(global::Tsu.Trees.RedGreen.Sample.SampleNode? parent) => new global::Tsu.Trees.RedGreen.Sample.FunctionCallExpressionSample(this, parent); - public global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample Update(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample secondArg) + public global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample Update(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample? secondArg) { if (identifier != this.Identifier && firstArg != this.FirstArg && secondArg != this.SecondArg) { @@ -231,7 +231,7 @@ internal static class SampleFactory public static global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample IdentifierExpression(string name) { #if DEBUG - if ((object)name == null) throw new global::System.ArgumentNullException(nameof(name)) + if (name == null) throw new global::System.ArgumentNullException(nameof(name)); #endif // DEBUG return new global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample( @@ -250,8 +250,8 @@ internal static class SampleFactory public static global::Tsu.Trees.RedGreen.Sample.Internal.BinaryOperationExpressionSample BinaryOperationExpression(global::Tsu.Trees.RedGreen.Sample.SampleKind kind, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample left, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample right) { #if DEBUG - if ((object)left == null) throw new global::System.ArgumentNullException(nameof(left)) - if ((object)right == null) throw new global::System.ArgumentNullException(nameof(right)) + if (left == null) throw new global::System.ArgumentNullException(nameof(left)); + if (right == null) throw new global::System.ArgumentNullException(nameof(right)); switch (kind) { case Tsu.Trees.RedGreen.Sample.SampleKind.AdditionExpression: @@ -271,20 +271,20 @@ internal static class SampleFactory public static global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample FunctionCallExpression(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg) { #if DEBUG - if ((object)identifier == null) throw new global::System.ArgumentNullException(nameof(identifier)) - if ((object)firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg)) + if (identifier == null) throw new global::System.ArgumentNullException(nameof(identifier)); + if (firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg)); #endif // DEBUG return new global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample( - global::Tsu.Trees.RedGreen.Sample.SampleKind.FunctionCallExpression, identifier, firstArg); + global::Tsu.Trees.RedGreen.Sample.SampleKind.FunctionCallExpression, identifier, firstArg, default); } - public static global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample FunctionCallExpression(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample secondArg) + public static global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample FunctionCallExpression(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample? secondArg) { #if DEBUG - if ((object)identifier == null) throw new global::System.ArgumentNullException(nameof(identifier)) - if ((object)firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg)) - if ((object)secondArg == null) throw new global::System.ArgumentNullException(nameof(secondArg)) + if (identifier == null) throw new global::System.ArgumentNullException(nameof(identifier)); + if (firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg)); + if (secondArg == null) throw new global::System.ArgumentNullException(nameof(secondArg)); #endif // DEBUG return new global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample( diff --git a/Tsu.Trees.RedGreen/sourcegen/GreenTreeGenerator.cs b/Tsu.Trees.RedGreen/sourcegen/GreenTreeGenerator.cs index 7bbe0ca..f9df898 100644 --- a/Tsu.Trees.RedGreen/sourcegen/GreenTreeGenerator.cs +++ b/Tsu.Trees.RedGreen/sourcegen/GreenTreeGenerator.cs @@ -67,9 +67,9 @@ private static void WriteGreenRoot(this IndentedTextWriter writer, Tree tree, No { writer.WriteLine("abstract partial class {0} : global::Tsu.Trees.RedGreen.Internal.IGreenNode<{1}, {2}, {3}>", root.TypeSymbol.Name, - tree.GreenBase.ToCSharpString(), - tree.RedBase.ToCSharpString(), - tree.KindEnum.ToCSharpString()); + tree.GreenBase.ToCSharpString(false), + tree.RedBase.ToCSharpString(false), + tree.KindEnum.ToCSharpString(false)); writer.WriteLine('{'); writer.Indent++; { @@ -120,7 +120,7 @@ private static void WriteGreenRoot(this IndentedTextWriter writer, Tree tree, No writer.Indent++; { writer.WriteLine("var node = this.GetSlot(index);"); - writer.WriteLine("Debug.Assert((object)node != null)"); + writer.WriteLine("Debug.Assert(node != null);"); writer.WriteLine("return node!;"); } writer.Indent--; @@ -229,7 +229,7 @@ private static void WriteGreenNode(this IndentedTextWriter writer, Tree tree, No { if (node.TypeSymbol.IsAbstract) writer.Write("abstract "); - writer.WriteLine("partial class {0} : {1}", node.TypeSymbol.Name, node.BaseSymbol!.ToCSharpString()); + writer.WriteLine("partial class {0} : {1}", node.TypeSymbol.Name, node.BaseSymbol!.ToCSharpString(false)); writer.WriteLine('{'); writer.Indent++; { @@ -433,18 +433,18 @@ private static void WriteGreenFactoryMethods(this IndentedTextWriter writer, Tre { if (node.RequiredComponents.Any(x => x.IsOptional)) { - var nonOptionalRequired = node.RequiredComponents.Where(x => !x.IsOptional); - writeMethod(writer, tree, node, nonOptionalRequired); + writeMethod(writer, tree, node, false); writer.WriteLineNoTabs(""); } - writeMethod(writer, tree, node, node.RequiredComponents); + writeMethod(writer, tree, node, true); - static void writeMethod(IndentedTextWriter writer, Tree tree, Node node, IEnumerable components) + static void writeMethod(IndentedTextWriter writer, Tree tree, Node node, bool includeOptional) { writer.Write("public static {0} {1}(", node.TypeSymbol.ToCSharpString(), node.TypeSymbol.Name.WithoutSuffix(tree.Suffix)); var first = true; - foreach (var component in components) + foreach (var component in node.RequiredComponents) { + if (!includeOptional && component.IsOptional) continue; if (!first) writer.Write(", "); first = false; writer.Write("{0} {1}", component.Type.ToCSharpString(), component.ParameterName); @@ -454,8 +454,11 @@ static void writeMethod(IndentedTextWriter writer, Tree tree, Node node, IEnumer writer.Indent++; { writer.WriteLineNoTabs("#if DEBUG"); - foreach (var component in components.Where(x => !x.Type.IsValueType)) - writer.WriteLine("if ((object){0} == null) throw new global::System.ArgumentNullException(nameof({0}))", component.ParameterName); + foreach (var component in node.RequiredComponents.Where(x => !x.Type.IsValueType)) + { + if (!includeOptional && component.IsOptional) continue; + writer.WriteLine("if ({0} == null) throw new global::System.ArgumentNullException(nameof({0}));", component.ParameterName); + } if (node.Kinds.Length != 1) { writer.WriteLine("switch (kind)"); @@ -485,11 +488,14 @@ static void writeMethod(IndentedTextWriter writer, Tree tree, Node node, IEnumer first = false; writer.Write("global::{0}", node.Kinds[0].ToCSharpString()); } - foreach (var component in components) + foreach (var component in node.RequiredComponents) { if (!first) writer.Write(", "); first = false; - writer.Write(component.ParameterName); + if (component.IsOptional && !includeOptional) + writer.Write("default"); + else + writer.Write(component.ParameterName); } writer.WriteLine(");"); } diff --git a/Tsu.Trees.RedGreen/sourcegen/Utils.cs b/Tsu.Trees.RedGreen/sourcegen/Utils.cs index 82852c0..0295571 100644 --- a/Tsu.Trees.RedGreen/sourcegen/Utils.cs +++ b/Tsu.Trees.RedGreen/sourcegen/Utils.cs @@ -46,9 +46,19 @@ public static string ToCSharpString(this Accessibility accessibility) => _ => throw new NotImplementedException() }; - public static string ToCSharpString(this ISymbol symbol) => symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + public static string ToCSharpString(this ITypeSymbol symbol, bool addNullable = true) + { + var str = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + if (addNullable && symbol.NullableAnnotation is NullableAnnotation.Annotated) + str += '?'; + return str; + } - public static string ToCSharpString(this INamespaceSymbol symbol) => symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Substring("global::".Length); + public static string ToCSharpString(this INamespaceSymbol symbol, bool noGlobal = true) + { + var str = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + return noGlobal ? str.Substring("global::".Length) : str; + } public static SourceText ToSourceText(this StringBuilder builder) => SourceText.From(new StringBuilderReader(builder), builder.Length, Encoding.UTF8);