private void WriteClassesImpl()

in src/Kusto.Language/Syntax/CodeGen/CslTreeGenerator.cs [399:634]


        private void WriteClassesImpl()
        {
            bool first = true;
            foreach (var c in m_classes)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    m_writer.WriteLine();
                }

                m_writer.WriteRegion($"class {c.Name}", () =>
                {
                    m_writer.WriteEmptyLineIfNeeded();
                    m_writer.WriteDocString(c.Doc, c.Remarks);
                    m_writer.WriteScope($"public {GetAbstractOrSealed(c)}partial class {c.Name} : {c.Base}", () =>
                    {
                        // #region Properties
                        if (c.Properties != null /* && c.Properties.Length > 0 */)
                        {
                            if (!c.Abstract)
                            {
                                m_writer.WriteEmptyLineIfNeeded();
                                if (c.Kind != null)
                                {
                                    m_writer.WriteLine($"public override SyntaxKind Kind => SyntaxKind.{c.Kind};");
                                }
                                else
                                {
                                    m_writer.WriteLine("private readonly SyntaxKind kind;");
                                    m_writer.WriteLine("public override SyntaxKind Kind => this.kind;");
                                }
                            }

                            foreach (var property in c.Properties)
                            {
                                m_writer.WriteEmptyLineIfNeeded();
                                m_writer.WriteDocString(property.Doc/*, property.Remarks*/);
                                if (property.PublicSetter)
                                {
                                    m_writer.WriteLine($"public {property.Type} {property.Name} {{ get; set; }}");
                                }
                                else
                                {
                                    m_writer.WriteLine($"public {property.Type} {property.Name} {{ get; }}");
                                }
                            }
                        }

                        m_writer.WriteEmptyLineIfNeeded();
                        m_writer.WriteDocString($@"Constructs a new instance of <see cref=""{c.Name}""/>.");

                        var lineage = GetLineage(c);
                        var props = lineage.Select(cslNode => cslNode.Properties).ToList();
                        var flattenedProps = props.SelectMany(propsArray => propsArray.Select(propsArrayItem => propsArrayItem)).ToList();

                        var constructorParametersList = 
                            string.Join(", ", 
                                flattenedProps.Select(property => 
                                    $"{property.Type} {CodeGenerator.GetCamelCase(property.Name)}{(property.DefaultValue != null ? " = " + property.DefaultValue : "")}")
                            .Concat(new[] { "IReadOnlyList<Diagnostic> diagnostics = null" }));

                        if (c.Kind == null && !c.Abstract)
                        {
                            constructorParametersList = "SyntaxKind kind, " + constructorParametersList;
                        }

                        var flattenedBaseProps = props.Take(props.Count - 1).SelectMany(propsArray => propsArray.Select(propsArrayItem => propsArrayItem)).ToList();
                        var baseParametersList = string.Join(", ", flattenedBaseProps.Select(property => $"{CodeGenerator.GetCamelCase(property.Name)}")
                            .Concat(new[] { "diagnostics" }));

                        m_writer.WriteScope($"internal {c.Name}({constructorParametersList}) : base({baseParametersList})", () =>
                        {
                            if (!c.Abstract)
                            {
                                if (c.Kind == null)
                                {
                                    m_writer.WriteLine("this.kind = kind;");
                                }

                                foreach (var property in c.Properties)
                                {
                                    if (property.IsSyntax)
                                    {
                                        m_writer.WriteLine($"this.{property.Name} = Attach({CodeGenerator.GetCamelCase(property.Name)}{(property.Optional ? ", optional: true" : "")});");
                                    }
                                    else
                                    {
                                        m_writer.WriteLine($"this.{property.Name} = {CodeGenerator.GetCamelCase(property.Name)};");
                                    }
                                }

                                m_writer.WriteLine("this.Init();");
                            }
                        });

                        var syntaxProperties = c.Properties.Where(p => p.IsSyntax).ToArray();

                        if (!c.Abstract /*&& c.Properties.Length > 0*/)
                        {
                            // ChildCount
                            m_writer.WriteEmptyLineIfNeeded();
                            m_writer.WriteLine($"public override int ChildCount => {syntaxProperties.Length};");

                            // GetChild
                            m_writer.WriteEmptyLineIfNeeded();
                            m_writer.WriteScope("public override SyntaxElement GetChild(int index)", () =>
                            {
                                m_writer.WriteScope("switch (index)", () =>
                                {
                                    for (int i = 0; i < syntaxProperties.Length; i++)
                                    {
                                        m_writer.WriteLine($"case {i}: return {syntaxProperties[i].Name};");
                                    }

                                    m_writer.WriteLine("default: throw new ArgumentOutOfRangeException();");
                                });
                            });

                            // GetName
                            m_writer.WriteEmptyLineIfNeeded();
                            m_writer.WriteScope("public override string GetName(int index)", () =>
                            {
                                m_writer.WriteScope("switch (index)", () =>
                                {
                                    for (int i = 0; i < syntaxProperties.Length; i++)
                                    {
                                        m_writer.WriteLine($"case {i}: return nameof({syntaxProperties[i].Name});");
                                    }

                                    m_writer.WriteLine("default: throw new ArgumentOutOfRangeException();");
                                });
                            });

                            // IsOptional
                            if (syntaxProperties.Any(p => p.Optional))
                            {
                                m_writer.WriteEmptyLineIfNeeded();
                                m_writer.WriteScope("public override bool IsOptional(int index)", () =>
                                {
                                    m_writer.WriteScope("switch (index)", () =>
                                    {
                                        for (int i = 0; i < syntaxProperties.Length; i++)
                                        {
                                            if (syntaxProperties[i].Optional)
                                            {
                                                m_writer.WriteLine($"case {i}:");
                                            }
                                        }

                                        m_writer.WriteLine($"    return true;");

                                        m_writer.WriteLine($"default:");
                                        m_writer.WriteLine($"    return false;");
                                    });
                                });
                            }

                            // GetCompletionHint
                            if (syntaxProperties.Any(p => p.Completion != null))
                            {
                                m_writer.WriteEmptyLineIfNeeded();
                                m_writer.WriteScope("protected override CompletionHint GetCompletionHintCore(int index)", () =>
                                {
                                    m_writer.WriteScope("switch (index)", () =>
                                    {
                                        for (int i = 0; i < syntaxProperties.Length; i++)
                                        {
                                            if (syntaxProperties[i].Completion != null)
                                            {
                                                m_writer.WriteLine($"case {i}: return CompletionHint.{syntaxProperties[i].Completion};");
                                            }
                                        }

                                        m_writer.WriteLine($"default: return CompletionHint.Inherit;");
                                    });
                                });
                            }
                        }

                        // #region CslNode implementation
                        if (!c.Abstract)
                        {
                            m_writer.WriteEmptyLineIfNeeded();
                            m_writer.WriteScope($"public override void Accept(SyntaxVisitor visitor)", () =>
                            {
                                m_writer.WriteLine($"visitor.Visit{c.Name}(this);");
                            });

                            m_writer.WriteScope($"public override TResult Accept<TResult>(SyntaxVisitor<TResult> visitor)", () =>
                            {
                                m_writer.WriteLine($"return visitor.Visit{c.Name}(this);");
                            });

#if false
                            m_writer.WriteScope($"public override TResult Accept<TContext, TResult>(SyntaxVisitor<TContext, TResult> visitor, TContext context)", () =>
                            {
                                m_writer.WriteLine($"return visitor.Visit{c.Name}(context, this);");
                            });
#endif

                            if (c.CloneOptions != CslTreeGeneratorCloneOptions.Custom && c.Properties != null /*&& c.Properties.Length > 0*/)
                            {
                                var args = "";
                                if (c.Kind == null)
                                {
                                    args = "this.Kind";
                                }

                                if (c.Properties.Length > 0)
                                {
                                    if (args.Length > 0)
                                        args = args + ", ";

                                    args = args + string.Join(", ", c.Properties.Select(p => p.IsSyntax ? $"({p.Type}){p.Name}?.Clone(includeDiagnostics)" : p.Name));
                                }

                                if (args.Length > 0)
                                    args = args + ", ";

                                args = args + "(includeDiagnostics ? this.SyntaxDiagnostics : null)";

                                m_writer.WriteEmptyLineIfNeeded();
                                m_writer.WriteScope($"protected override SyntaxElement CloneCore(bool includeDiagnostics)", () =>
                                {
                                    m_writer.WriteLine($"return new {c.Name}({args});");
                                });
                            }
                        }
                    });
                });
            }
        }