Skip to content

Commit

Permalink
Got the const generator working, in some capacity.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeltyPlayer committed Apr 15, 2024
1 parent db15f74 commit f4f0c0d
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 63 deletions.
5 changes: 5 additions & 0 deletions Schema Build Tests/const/Something.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace foo {
public class Something {
public IConstValueType Field { get; set; }
}
}
9 changes: 9 additions & 0 deletions Schema Build Tests/const/ValueType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using schema.@const;


namespace foo {
[GenerateConst]
public partial class ValueType {
public string Value { get; set; }
}
}
48 changes: 41 additions & 7 deletions Schema Tests/const/BasicConstGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ internal class BasicConstGeneratorTests {
[TestCase("public bool field;")]
[TestCase("public bool Field { set; }")]
// Missing const attribute
[TestCase("public bool Field { get; set; }")]
[TestCase("public bool Field();")]
// Not accessible enough
[TestCase("[Const] private bool Field { get; set; }")]
[TestCase("private bool Field { get; set; }")]
[TestCase("[Const] bool Field();")]
public void TestEmpty(string emptySrc) {
ConstGeneratorTestUtil.AssertGenerated(
Expand All @@ -31,7 +30,7 @@ public partial class Empty {
namespace foo.bar {
public partial class Empty : IConstEmpty;

public partial class IConstEmpty {
public interface IConstEmpty {
}
}

Expand All @@ -56,7 +55,7 @@ public T1 Foo<T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4) { }
namespace foo.bar {
public partial class SimpleGenerics<T1, T2> : IConstSimpleGenerics<T1, T2>;

public partial class IConstSimpleGenerics<T1, T2> {
public interface IConstSimpleGenerics<T1, T2> {
public T1 Foo<T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4);
}
}
Expand Down Expand Up @@ -88,7 +87,7 @@ public T Foo<S>(T t, S s) where S : {{constraint}} { }
namespace foo.bar {
public partial class EachConstraint<T> : IConstEachConstraint<T>;

public partial class IConstEachConstraint<T> where T : {{constraint}} {
public interface IConstEachConstraint<T> where T : {{constraint}} {
public T Foo<S>(T t, S s) where S : {{constraint}};
}
}
Expand All @@ -107,15 +106,18 @@ namespace foo.bar {
public partial class SubConstraint<T1, T2> where T2 : T1 {
[Const]
public T1 Foo<S>(S s) where S : T1 { }

public T2 Bar { get; set; }
}
}
""",
"""
namespace foo.bar {
public partial class SubConstraint<T1, T2> : IConstSubConstraint<T1, T2>;

public partial class IConstSubConstraint<T1, T2> where T2 : T1 {
public interface IConstSubConstraint<T1, T2> where T2 : T1 {
public T1 Foo<S>(S s) where S : T1;
public T2 Bar { get; }
}
}

Expand All @@ -133,15 +135,47 @@ namespace foo.bar {
public partial class SimpleAttributes<T1, T2> where T1 : notnull, struct where T2 : unmanaged {
[Const]
public T1 Foo<T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4) where T3 : class where T4 : class? { }

public T2 Bar { get; set; }
}
}
""",
"""
namespace foo.bar {
public partial class SimpleAttributes<T1, T2> : IConstSimpleAttributes<T1, T2>;

public partial class IConstSimpleAttributes<T1, T2> where T1 : notnull, struct where T2 : unmanaged {
public interface IConstSimpleAttributes<T1, T2> where T1 : notnull, struct where T2 : unmanaged {
public T1 Foo<T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4) where T3 : class where T4 : class?;
public T2 Bar { get; }
}
}

""");
}

[Test]
public void TestKeywords() {
ConstGeneratorTestUtil.AssertGenerated(
"""
using schema.@const;

namespace @const {
[GenerateConst]
public partial class @void<@double> where @double : struct {
[Const]
public @void @int<@short>(@void @bool) where @short : @void { }

public @void @float { get; }
}
}
""",
"""
namespace @const {
public partial class @void<@double> : IConstvoid<@double>;

public interface IConstvoid<@double> where @double : struct {
public @void @int<@short>(@void @bool) where @short : @void;
public @void @float { get; }
}
}

Expand Down
9 changes: 4 additions & 5 deletions Schema Tests/const/ConstGeneratorTestUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal static class ConstGeneratorTestUtil {
public static void AssertGenerated(string src, string expected) {
var syntaxTree = CSharpSyntaxTree.ParseText(src);
var compilation = BinarySchemaTestUtil.Compilation.Clone()
.AddSyntaxTrees(syntaxTree);
.AddSyntaxTrees(syntaxTree);

var semanticModel = compilation.GetSemanticModel(syntaxTree);

Expand Down Expand Up @@ -80,14 +80,13 @@ var symbol
var namedTypeSymbol
= symbol as INamedTypeSymbol;
return (typeNode, namedTypeSymbol);
return namedTypeSymbol;
})
.ToArray();

var (syntax, synbol) = structures.First();
var synbol = structures.First();

Assert.True(
new ConstTypeGenerator().Generate(syntax, synbol, out var actual));
Assert.True(new ConstTypeGenerator().Generate(synbol, out var actual));

Assert.AreEqual(expected, actual.ReplaceLineEndings());
}
Expand Down
2 changes: 0 additions & 2 deletions Schema/src/binary/BinarySchemaGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

using schema.binary.attributes;
using schema.binary.text;
Expand All @@ -14,7 +13,6 @@

namespace schema.binary {
[Generator(LanguageNames.CSharp)]
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class BinarySchemaGenerator
: BNamedTypeSecondaryGenerator<IBinarySchemaContainer> {
private readonly BinarySchemaContainerParser parser_ = new();
Expand Down
26 changes: 16 additions & 10 deletions Schema/src/const/ConstTypeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

Expand All @@ -12,28 +13,27 @@
using schema.util.types;

namespace schema.@const {
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
[AttributeUsage(AttributeTargets.Method)]
public class ConstAttribute : Attribute;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class GenerateConstAttribute : Attribute;

[Generator(LanguageNames.CSharp)]
public class ConstTypeGenerator : BNamedTypeGenerator {
public const string PREFIX = "IConst";

internal override void Generate(
TypeDeclarationSyntax syntax,
INamedTypeSymbol typeSymbol,
ISourceFileDictionary sourceFileDictionary) {
var typeV2 = TypeV2.FromSymbol(typeSymbol);
if (this.Generate(syntax, typeSymbol, out var source)) {
if (this.Generate(typeSymbol, out var source)) {
sourceFileDictionary.Add($"{typeV2.FullyQualifiedName}_const.g",
source);
}
}

public bool Generate(TypeDeclarationSyntax syntax,
INamedTypeSymbol typeSymbol,
public bool Generate(INamedTypeSymbol typeSymbol,
out string source) {
var typeV2 = TypeV2.FromSymbol(typeSymbol);

Expand Down Expand Up @@ -69,8 +69,13 @@ public bool Generate(TypeDeclarationSyntax syntax,

// Interface
{
cbsb.EnterBlock(typeSymbol.GetQualifiersAndNameAndGenericsFor(PREFIX) +
typeSymbol.TypeParameters.GetTypeConstraints(typeV2));
cbsb.Write(
SymbolTypeUtil.AccessibilityToModifier(
typeSymbol.DeclaredAccessibility));
cbsb.Write(" interface ");
cbsb.EnterBlock(
typeSymbol.GetNameAndGenericsFor(PREFIX) +
typeSymbol.TypeParameters.GetTypeConstraints(typeV2));

foreach (var parsedMember in new TypeInfoParser().ParseMembers(
typeSymbol)) {
Expand All @@ -94,7 +99,8 @@ public bool Generate(TypeDeclarationSyntax syntax,
continue;
}

if (!memberSymbol.HasAttribute<ConstAttribute>()) {
if (memberSymbol is IMethodSymbol &&
!memberSymbol.HasAttribute<ConstAttribute>()) {
continue;
}

Expand All @@ -113,7 +119,7 @@ public bool Generate(TypeDeclarationSyntax syntax,
cbsb.Write(typeV2.GetQualifiedNameFromCurrentSymbol(memberTypeV2));
cbsb.Write(" ");

cbsb.Write(memberSymbol.Name);
cbsb.Write(memberSymbol.Name.EscapeKeyword());

switch (memberSymbol) {
case IMethodSymbol methodSymbol: {
Expand All @@ -130,7 +136,7 @@ public bool Generate(TypeDeclarationSyntax syntax,
cbsb.Write(
typeV2.GetQualifiedNameFromCurrentSymbol(parameterTypeV2));
cbsb.Write(" ");
cbsb.Write(parameterSymbol.Name);
cbsb.Write(parameterSymbol.Name.EscapeKeyword());
}

cbsb.Write(")");
Expand Down
37 changes: 20 additions & 17 deletions Schema/src/util/generators/BNamedTypeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

using schema.util.data;


namespace schema.util.generators {
public abstract class BNamedTypeGenerator : ISourceGenerator {
private readonly Queue<INamedTypeSymbol> symbolQueue_ = new();

private readonly SourceFileDictionary sourceFileDictionary_ = new();

internal abstract void Generate(
TypeDeclarationSyntax syntax,
INamedTypeSymbol typeSymbol,
ISourceFileDictionary sourceFileDictionary);
internal abstract void Generate(INamedTypeSymbol typeSymbol,
ISourceFileDictionary sourceFileDictionary);

public void Initialize(GeneratorInitializationContext context)
=> context.RegisterForSyntaxNotifications(() => new CustomReceiver(this));

private class CustomReceiver : ISyntaxContextReceiver {
private readonly BNamedTypeGenerator g_;

public CustomReceiver(BNamedTypeGenerator g) {
this.g_ = g;
}

private class CustomReceiver(BNamedTypeGenerator g)
: ISyntaxContextReceiver {
public void OnVisitSyntaxNode(GeneratorSyntaxContext context) {
TypeDeclarationSyntax syntax;
ISymbol symbol;
Expand All @@ -39,13 +39,16 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) {
return;
}

this.g_.Generate(syntax,
namedTypeSymbol,
this.g_.sourceFileDictionary_);
g.symbolQueue_.Enqueue(namedTypeSymbol);
}
}

public void Execute(GeneratorExecutionContext context)
=> this.sourceFileDictionary_.SetHandler(context.AddSource);
public void Execute(GeneratorExecutionContext context) {
while (this.symbolQueue_.TryDequeue(out var symbol)) {
this.Generate(symbol, this.sourceFileDictionary_);
}

this.sourceFileDictionary_.SetHandler(context.AddSource);
}
}
}
14 changes: 5 additions & 9 deletions Schema/src/util/generators/BNamedTypeSecondaryGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@


namespace schema.util.generators {
internal abstract class BNamedTypeSecondaryGenerator<TSecondary> : ISourceGenerator {
internal abstract class BNamedTypeSecondaryGenerator<TSecondary>
: ISourceGenerator {
private readonly Queue<(INamedTypeSymbol, TypeDeclarationSyntax)>
symbolSyntaxQueue_ = new();

Expand All @@ -30,13 +31,8 @@ internal abstract void Generate(
public void Initialize(GeneratorInitializationContext context)
=> context.RegisterForSyntaxNotifications(() => new CustomReceiver(this));

private class CustomReceiver : ISyntaxContextReceiver {
private readonly BNamedTypeSecondaryGenerator<TSecondary> g_;

public CustomReceiver(BNamedTypeSecondaryGenerator<TSecondary> g) {
this.g_ = g;
}

private class CustomReceiver(BNamedTypeSecondaryGenerator<TSecondary> g)
: ISyntaxContextReceiver {
public void OnVisitSyntaxNode(GeneratorSyntaxContext context) {
TypeDeclarationSyntax syntax;
ISymbol symbol;
Expand All @@ -54,7 +50,7 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) {
return;
}

this.g_.symbolSyntaxQueue_.Enqueue((namedTypeSymbol, syntax));
g.symbolSyntaxQueue_.Enqueue((namedTypeSymbol, syntax));
}
}

Expand Down
Loading

0 comments on commit f4f0c0d

Please sign in to comment.