116 lines
3.6 KiB
C#
116 lines
3.6 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
|
|
namespace MfGames.Nitride.Generators;
|
|
|
|
/// <summary>
|
|
/// Implements a source generator that creates Set* methods for the various
|
|
/// properties that also returns the same object for purposes of chaining
|
|
/// together calls.
|
|
/// </summary>
|
|
[Generator]
|
|
public class WithPropertiesSourceGenerator
|
|
: ClassAttributeSourceGeneratorBase<WithPropertiesSyntaxReceiver>
|
|
{
|
|
/// <inheritdoc />
|
|
protected override WithPropertiesSyntaxReceiver CreateSyntaxReceiver(
|
|
GeneratorInitializationContext context)
|
|
{
|
|
return new WithPropertiesSyntaxReceiver(context);
|
|
}
|
|
|
|
protected override void GenerateClassFile(
|
|
GeneratorExecutionContext context,
|
|
ClassAttributeReference unit)
|
|
{
|
|
// Pull out some fields.
|
|
ClassDeclarationSyntax cds = unit.ClassDeclaration;
|
|
|
|
// Create the partial class.
|
|
StringBuilder buffer = new();
|
|
buffer.AppendLine("#nullable enable");
|
|
|
|
// Copy the using statements from the file.
|
|
foreach (UsingDirectiveSyntax? uds in unit.UsingDirectiveList)
|
|
{
|
|
buffer.AppendLine(uds.ToString());
|
|
}
|
|
|
|
buffer.AppendLine();
|
|
|
|
// Create the namespace.
|
|
buffer.AppendLine($"namespace {unit.Namespace}");
|
|
buffer.AppendLine("{");
|
|
buffer.AppendLine($" public partial class {cds.Identifier}");
|
|
buffer.AppendLine(" {");
|
|
|
|
// Go through the properties of the namespace.
|
|
IEnumerable<PropertyDeclarationSyntax> properties = cds.Members
|
|
.Where(m => m.Kind() == SyntaxKind.PropertyDeclaration)
|
|
.Cast<PropertyDeclarationSyntax>();
|
|
|
|
bool first = true;
|
|
|
|
foreach (PropertyDeclarationSyntax pds in properties)
|
|
{
|
|
// See if we have a setter.
|
|
bool found = pds.AccessorList?.Accessors
|
|
.Any(x => x.Keyword.ToString() == "set")
|
|
?? false;
|
|
|
|
if (!found)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If we aren't first, then add a newline before it.
|
|
if (first)
|
|
{
|
|
first = false;
|
|
}
|
|
else
|
|
{
|
|
buffer.AppendLine();
|
|
}
|
|
|
|
// Write some documentation.
|
|
buffer.AppendLine(" /// <summary>");
|
|
|
|
buffer.AppendLine(
|
|
string.Format(
|
|
" /// Sets the {0} value and returns the operation for chaining.",
|
|
pds.Identifier.ToString()));
|
|
|
|
buffer.AppendLine(" /// </summary>");
|
|
|
|
// We have the components for writing out a setter.
|
|
buffer.AppendLine(
|
|
string.Format(
|
|
" public virtual {0} With{1}({2} value)",
|
|
cds.Identifier,
|
|
pds.Identifier,
|
|
pds.Type));
|
|
|
|
buffer.AppendLine(" {");
|
|
buffer.AppendLine(
|
|
string.Format(" this.{0} = value;", pds.Identifier));
|
|
buffer.AppendLine(" return this;");
|
|
buffer.AppendLine(" }");
|
|
}
|
|
|
|
// Finish up the class.
|
|
buffer.AppendLine(" }");
|
|
buffer.AppendLine("}");
|
|
|
|
// Create the source text and write out the file.
|
|
var sourceText = SourceText.From(buffer.ToString(), Encoding.UTF8);
|
|
context.AddSource(cds.Identifier + ".Generated.cs", sourceText);
|
|
}
|
|
}
|