mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-15 03:20:30 +00:00
87 lines
2.9 KiB
C#
87 lines
2.9 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
namespace osu.Framework.SourceGeneration.Generators
|
|
{
|
|
public abstract class IncrementalSourceEmitter
|
|
{
|
|
protected abstract string FileSuffix { get; }
|
|
|
|
private const string headers = @"// <auto-generated/>
|
|
#nullable enable
|
|
#pragma warning disable CS4014
|
|
|
|
";
|
|
|
|
public readonly IncrementalSemanticTarget Target;
|
|
|
|
protected IncrementalSourceEmitter(IncrementalSemanticTarget target)
|
|
{
|
|
Target = target;
|
|
}
|
|
|
|
public void Emit(AddSourceDelegate addSource)
|
|
{
|
|
if (!Target.IsValid)
|
|
return;
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
result.Append(headers);
|
|
|
|
if (Target.ContainingNamespace == null)
|
|
{
|
|
result.Append(
|
|
emitTypeTree().NormalizeWhitespace());
|
|
}
|
|
else
|
|
{
|
|
result.Append(
|
|
SyntaxFactory.NamespaceDeclaration(
|
|
SyntaxFactory.IdentifierName(Target.ContainingNamespace))
|
|
.WithMembers(
|
|
SyntaxFactory.SingletonList(
|
|
emitTypeTree()))
|
|
.NormalizeWhitespace());
|
|
}
|
|
|
|
// Fully qualified name, with generics replaced with friendly characters.
|
|
string typeName = Target.FullyQualifiedTypeName.Replace('<', '{').Replace('>', '}');
|
|
string filename = $"g_{typeName}_{FileSuffix}.cs";
|
|
|
|
addSource(filename, result.ToString());
|
|
}
|
|
|
|
protected abstract ClassDeclarationSyntax ConstructClass(ClassDeclarationSyntax initialClass);
|
|
|
|
private MemberDeclarationSyntax emitTypeTree()
|
|
{
|
|
List<ClassDeclarationSyntax> classes = new List<ClassDeclarationSyntax>();
|
|
|
|
foreach (string type in Target.TypeHierarchy)
|
|
classes.Add(createClassSyntax(type));
|
|
|
|
classes[0] = ConstructClass(classes[0]);
|
|
|
|
for (int i = 0; i < classes.Count - 1; i++)
|
|
classes[i + 1] = classes[i + 1].WithMembers(SyntaxFactory.List<MemberDeclarationSyntax>(new[] { classes[i] }));
|
|
|
|
return classes.Last();
|
|
|
|
static ClassDeclarationSyntax createClassSyntax(string type) =>
|
|
SyntaxFactory.ClassDeclaration(type)
|
|
.WithModifiers(
|
|
SyntaxTokenList.Create(
|
|
SyntaxFactory.Token(SyntaxKind.PartialKeyword)));
|
|
}
|
|
}
|
|
|
|
public delegate void AddSourceDelegate(string filename, string sourceText);
|
|
}
|