Skip to content

Commit

Permalink
Implemented first pass at const interface generating code.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeltyPlayer committed Apr 14, 2024
1 parent 87048de commit e49f6cc
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Schema/src/binary/text/BinarySchemaReaderGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ public string Generate(IBinarySchemaContainer container) {
}

foreach (var declaringType in declaringTypes) {
cbsb.EnterBlock(declaringType.GetQualifiersAndNameFor());
cbsb.EnterBlock(declaringType.GetQualifiersAndNameAndGenericsFor());
}

cbsb.EnterBlock(typeSymbol.GetQualifiersAndNameFor());
cbsb.EnterBlock(typeSymbol.GetQualifiersAndNameAndGenericsFor());

cbsb.EnterBlock($"public void Read(IBinaryReader {READER})");
{
Expand Down
4 changes: 2 additions & 2 deletions Schema/src/binary/text/BinarySchemaWriterGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ public string Generate(IBinarySchemaContainer container) {
}

foreach (var declaringType in declaringTypes) {
cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameFor(declaringType));
cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameAndGenericsFor(declaringType));
}

cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameFor(typeSymbol));
cbsb.EnterBlock(SymbolTypeUtil.GetQualifiersAndNameAndGenericsFor(typeSymbol));

cbsb.EnterBlock($"public void Write(IBinaryWriter {WRITER})");
{
Expand Down
136 changes: 136 additions & 0 deletions Schema/src/const/ConstTypeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using System;
using System.IO;
using System.Text;

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

using schema.binary.parser;
using schema.util.generators;
using schema.util.symbols;
using schema.util.text;
using schema.util.types;

namespace schema.@const {
public class ConstAttribute : Attribute;

public class GenerateConstAttribute : Attribute;

public class ConstTypeGenerator : BNamedTypeGenerator {
internal override void Generate(
TypeDeclarationSyntax syntax,
INamedTypeSymbol typeSymbol,
ISourceFileDictionary sourceFileDictionary) {
var typeV2 = TypeV2.FromSymbol(typeSymbol);

if (!typeV2.HasAttribute<GenerateConstAttribute>()) {
return;
}

var typeNamespace = typeSymbol.GetFullyQualifiedNamespace();

var declaringTypes = typeSymbol.GetDeclaringTypesDownward();

var sb = new StringBuilder();
using var cbsb = new CurlyBracketTextWriter(new StringWriter(sb));

// TODO: Handle fancier cases here
if (typeNamespace != null) {
cbsb.EnterBlock($"namespace {typeNamespace}");
}

foreach (var declaringType in declaringTypes) {
cbsb.EnterBlock(declaringType.GetQualifiersAndNameAndGenericsFor());
}

// Interface
{
cbsb.EnterBlock(typeSymbol.GetQualifiersAndNameAndGenericsFor("I"));

foreach (var parsedMember in new TypeInfoParser().ParseMembers(
typeSymbol)) {
var (parseStatus, memberSymbol, memberTypeSymbol, _) = parsedMember;
if (parseStatus ==
TypeInfoParser.ParseStatus.NOT_A_FIELD_OR_PROPERTY_OR_METHOD) {
continue;
}

if (memberSymbol is IFieldSymbol) {
continue;
}

if (memberSymbol is IPropertySymbol { IsWriteOnly: true }) {
continue;
}

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

cbsb.Write(
SymbolTypeUtil.AccessibilityToModifier(
typeSymbol.DeclaredAccessibility));
cbsb.Write(" ");

var memberTypeV2 = TypeV2.FromSymbol(memberTypeSymbol);
cbsb.Write(typeV2.GetQualifiedNameFromCurrentSymbol(memberTypeV2));
cbsb.Write(" ");

cbsb.Write(memberSymbol.Name);

switch (memberSymbol) {
case IMethodSymbol methodSymbol: {
cbsb.Write(methodSymbol.TypeParameters.GetGenerics());
cbsb.Write("(");

for (var i = 0; i < methodSymbol.Parameters.Length; ++i) {
if (i > 0) {
cbsb.Write(", ");
}

var parameterSymbol = methodSymbol.Parameters[i];
var parameterTypeV2 = TypeV2.FromSymbol(parameterSymbol.Type);
cbsb.Write(
typeV2.GetQualifiedNameFromCurrentSymbol(parameterTypeV2));
cbsb.Write(" ");
cbsb.Write(parameterSymbol.Name);
}

cbsb.WriteLine(")");
break;
}
case IPropertySymbol: {
cbsb.WriteLine(" { get; }");
break;
}
}
}

cbsb.ExitBlock();
}

// Class
{
cbsb.EnterBlock(
typeSymbol.GetQualifiersAndNameAndGenericsFor() +
": " +
typeSymbol.GetNameAndGenericsFor("I"));

cbsb.ExitBlock();
}

// parent types
foreach (var declaringType in declaringTypes) {
cbsb.ExitBlock();
}

// namespace
if (typeNamespace != null) {
cbsb.ExitBlock();
}

sourceFileDictionary.Add($"{typeV2.FullyQualifiedName}_const.g",
sb.ToString());
}
}
}
4 changes: 2 additions & 2 deletions Schema/src/util/generators/BNamedTypeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@


namespace schema.util.generators {
internal abstract class BNamedTypeGenerator : ISourceGenerator {
public abstract class BNamedTypeGenerator : ISourceGenerator {
private readonly SourceFileDictionary sourceFileDictionary_ = new();

internal abstract bool Generate(
internal abstract void Generate(
TypeDeclarationSyntax syntax,
INamedTypeSymbol typeSymbol,
ISourceFileDictionary sourceFileDictionary);
Expand Down
107 changes: 77 additions & 30 deletions Schema/src/util/symbols/SymbolTypeUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ internal static bool IsInNamespace(
}
}

return fullNamespaceI == -1 && currentNamespaceI == -1 &&
return fullNamespaceI == -1 &&
currentNamespaceI == -1 &&
currentNamespace.ContainingNamespace.Name.Length == 0;
}

Expand All @@ -69,7 +70,7 @@ internal static bool IsInNamespace(
if (containingNamespaces.Length == 0) {
return null;
}

return string.Join(".", containingNamespaces);
}

Expand Down Expand Up @@ -119,7 +120,8 @@ internal static IEnumerable<AttributeData>
.GetAttributes()
.Where(attributeData
=> attributeData.AttributeClass?.IsExactlyType(
attributeType) ?? false);
attributeType) ??
false);
}


Expand All @@ -144,15 +146,16 @@ internal static IEnumerable<TAttribute> GetAttributes<TAttribute>(
where TAttribute : Attribute
=> symbol.GetAttributeData<TAttribute>()
.Select(attributeData => {
var attribute = attributeData.Instantiate<TAttribute>(symbol);
if (attribute is BMemberAttribute memberAttribute) {
memberAttribute.Init(diagnosticReporter,
symbol.ContainingType,
symbol.Name);
}
var attribute
= attributeData.Instantiate<TAttribute>(symbol);
if (attribute is BMemberAttribute memberAttribute) {
memberAttribute.Init(diagnosticReporter,
symbol.ContainingType,
symbol.Name);
}
return attribute;
});
return attribute;
});

public static IEnumerable<ISymbol> GetInstanceMembers(
this INamedTypeSymbol containerSymbol) {
Expand Down Expand Up @@ -202,17 +205,60 @@ public static INamedTypeSymbol[] GetDeclaringTypesDownward(
return declaringTypes.ToArray();
}

public static string GetQualifiersAndNameFor(
this INamedTypeSymbol namedTypeSymbol) {
var sb = new StringBuilder();
sb.Append(namedTypeSymbol.GetSymbolQualifiers());
sb.Append(" ");
public static string GetQualifiersAndNameAndGenericsFor(
this INamedTypeSymbol namedTypeSymbol,
string namePrefix = "")
=> new StringBuilder()
.AppendQualifiersAndNameAndGenericsFor(namedTypeSymbol, namePrefix)
.ToString();

public static StringBuilder AppendQualifiersAndNameAndGenericsFor(
this StringBuilder sb,
INamedTypeSymbol namedTypeSymbol,
string namePrefix = "")
=> sb.AppendSymbolQualifiers(namedTypeSymbol)
.Append(" ")
.AppendNameAndGenericsFor(namedTypeSymbol, namePrefix);

public static string GetNameAndGenericsFor(
this INamedTypeSymbol namedTypeSymbol,
string namePrefix = "")
=> new StringBuilder()
.AppendNameAndGenericsFor(namedTypeSymbol, namePrefix)
.ToString();

public static StringBuilder AppendNameAndGenericsFor(
this StringBuilder sb,
INamedTypeSymbol namedTypeSymbol,
string namePrefix = "") {
sb.Append(namePrefix);
sb.Append(namedTypeSymbol.Name);
sb.AppendGenericsFor(namedTypeSymbol);
return sb;
}

var typeParameters = namedTypeSymbol.TypeParameters;
if (typeParameters.Length > 0) {
public static string GetGenerics(this INamedTypeSymbol namedTypeSymbol)
=> new StringBuilder()
.AppendGenericsFor(namedTypeSymbol)
.ToString();

public static StringBuilder AppendGenericsFor(
this StringBuilder sb,
INamedTypeSymbol namedTypeSymbol)
=> sb.AppendGenerics(namedTypeSymbol.TypeParameters);

public static string GetGenerics(
this IReadOnlyList<ITypeParameterSymbol> typeParameters)
=> new StringBuilder()
.AppendGenerics(typeParameters)
.ToString();

public static StringBuilder AppendGenerics(
this StringBuilder sb,
IReadOnlyList<ITypeParameterSymbol> typeParameters) {
if (typeParameters.Count > 0) {
sb.Append("<");
for (var i = 0; i < typeParameters.Length; ++i) {
for (var i = 0; i < typeParameters.Count; ++i) {
if (i > 0) {
sb.Append(", ");
}
Expand All @@ -224,22 +270,23 @@ public static string GetQualifiersAndNameFor(
sb.Append(">");
}

return sb.ToString();
return sb;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetSymbolQualifiers(this INamedTypeSymbol typeSymbol)
=> (typeSymbol.IsStatic ? "static " : "") +
SymbolTypeUtil.AccessibilityToModifier(
typeSymbol.DeclaredAccessibility) +
" " +
(typeSymbol.IsAbstract ? "abstract " : "") +
"partial " +
(typeSymbol.TypeKind == TypeKind.Class ? "class" : "struct");
public static StringBuilder AppendSymbolQualifiers(
this StringBuilder sb,
INamedTypeSymbol typeSymbol)
=> sb.Append(typeSymbol.IsStatic ? "static " : "")
.Append(SymbolTypeUtil.AccessibilityToModifier(
typeSymbol.DeclaredAccessibility))
.Append(" ")
.Append(typeSymbol.IsAbstract ? "abstract " : "")
.Append("partial ")
.Append(typeSymbol.TypeKind == TypeKind.Class ? "class" : "struct");

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string AccessibilityToModifier(
Accessibility accessibility)
public static string AccessibilityToModifier(Accessibility accessibility)
=> accessibility switch {
Accessibility.Private => "private",
Accessibility.Protected => "protected",
Expand Down

0 comments on commit e49f6cc

Please sign in to comment.