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});");
});
}
}
});
});
}
}