Skip to content

Commit

Permalink
feat: Implement IIncrementalGenerator instead of ISourceGenerator
Browse files Browse the repository at this point in the history
Resolve #52
  • Loading branch information
SoftStoneDevelop committed May 21, 2023
1 parent 44ca619 commit e704aa1
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 89 deletions.
88 changes: 34 additions & 54 deletions Src/StackMemoryCollections/AttributeProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using StackMemoryCollections.Generators.Primitive;
using StackMemoryCollections.Helpers;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace StackMemoryCollections
Expand Down Expand Up @@ -34,72 +37,49 @@ internal class AttributeProcessor
private readonly Dictionary<string, Model.TypeInfo> _typeInfos = new Dictionary<string, Model.TypeInfo>();

public void FillAllTypes(
INamespaceOrTypeSymbol symbol
Compilation compilation,
ImmutableArray<TypeDeclarationSyntax> types
)
{
var queue = new Queue<INamespaceOrTypeSymbol>();
queue.Enqueue(symbol);

while (queue.Count != 0)
foreach (var typeDeclaration in types )
{
var current = queue.Dequeue();
if (current is INamedTypeSymbol type &&
!type.IsAbstract &&
!type.IsGenericType &&
!type.IsStatic &&
(type.IsValueType || type.IsReferenceType))
{
var attributes = type.GetAttributes();
var hasHelper = attributes.Any(wh => wh.AttributeClass.Name == "GenerateHelperAttribute");
var hasStack = attributes.Any(wh => wh.AttributeClass.Name == "GenerateStackAttribute");
var hasQueue = attributes.Any(wh => wh.AttributeClass.Name == "GenerateQueueAttribute");
var hasList = attributes.Any(wh => wh.AttributeClass.Name == "GenerateListAttribute");
var hasDictionary = attributes.Any(wh => wh.AttributeClass.Name == "GenerateDictionaryAttribute");
var hasWrapper = attributes.Any(wh => wh.AttributeClass.Name == "GenerateWrapperAttribute");

if (hasHelper || hasStack || hasQueue || hasList || hasDictionary || hasWrapper)
{
_typeHelpers.Add(type);
var type = compilation.GetSemanticModel(typeDeclaration.SyntaxTree).GetDeclaredSymbol(typeDeclaration);

if (hasStack)
{
_typeGeneratedStack.Add(type);
}
var attributes = type.GetAttributes();
var hasHelper = attributes.Any(wh => wh.AttributeClass.Name == "GenerateHelperAttribute");
var hasStack = attributes.Any(wh => wh.AttributeClass.Name == "GenerateStackAttribute");
var hasQueue = attributes.Any(wh => wh.AttributeClass.Name == "GenerateQueueAttribute");
var hasList = attributes.Any(wh => wh.AttributeClass.Name == "GenerateListAttribute");
var hasDictionary = attributes.Any(wh => wh.AttributeClass.Name == "GenerateDictionaryAttribute");
var hasWrapper = attributes.Any(wh => wh.AttributeClass.Name == "GenerateWrapperAttribute");

if (hasList)
{
_typeGeneratedList.Add(type);
}
if (hasHelper || hasStack || hasQueue || hasList || hasDictionary || hasWrapper)
{
_typeHelpers.Add(type);

if (hasQueue)
{
_typeGeneratedQueue.Add(type);
}
if (hasStack)
{
_typeGeneratedStack.Add(type);
}

if (hasDictionary)
{
_typeGeneratedDictionary.Add(type);
}
if (hasList)
{
_typeGeneratedList.Add(type);
}

if (hasWrapper)
{
_typeWrappers.Add(type);
}
if (hasQueue)
{
_typeGeneratedQueue.Add(type);
}
}
else if (current is INamespaceSymbol namespaceSymbol)
{
if (!_containCollections && namespaceSymbol.Name == "StackMemoryCollections")

if (hasDictionary)
{
_containCollections = true;
_typeGeneratedDictionary.Add(type);
}
}

foreach (var child in current.GetMembers())
{
if (child is INamespaceOrTypeSymbol symbolChild)
if (hasWrapper)
{
queue.Enqueue(symbolChild);
_typeWrappers.Add(type);
}
}
}
Expand Down Expand Up @@ -413,7 +393,7 @@ private bool HelperMustGenerated(in System.Collections.Immutable.ImmutableArray<
);
}

public void Generate(GeneratorExecutionContext context)
public void Generate(SourceProductionContext context)
{
if (!_containCollections)
{
Expand Down
96 changes: 88 additions & 8 deletions Src/StackMemoryCollections/Generator.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,102 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using StackMemoryCollections.Helpers;
using System.Collections.Immutable;
using System.Linq;

namespace StackMemoryCollections
{
[Generator]
public partial class Generator : ISourceGenerator
public partial class Generator : IIncrementalGenerator
{
public void Execute(GeneratorExecutionContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var c = (CSharpCompilation)context.Compilation;
var processor = new AttributeProcessor();
processor.FillAllTypes(c.Assembly.GlobalNamespace);
processor.Generate(context);
//System.Diagnostics.Debugger.Launch();
var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (s, _) => IsSyntaxTargetForGeneration(s),
transform: (ctx, _) => GetSemanticTargetForGeneration(ctx))
.Where(m => m != null);

var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());

context.RegisterSourceOutput(compilationAndClasses,
(spc, source) => Execute(source.Item1, source.Item2, spc));
}

static bool IsSyntaxTargetForGeneration(SyntaxNode node)
{
if(!(node is ClassDeclarationSyntax) && !(node is StructDeclarationSyntax))
{
return false;
}

var typeDeclar = (TypeDeclarationSyntax)node;
if (typeDeclar.Modifiers.Any(wh => wh.IsKind(SyntaxKind.StaticKeyword)))
{
return false;
}

if (typeDeclar.TypeParameterList?.Parameters.Any() == true)
{
return false;
}

if (typeDeclar.Modifiers.Any(wh => wh.IsKind(SyntaxKind.AbstractKeyword)))
{
return false;
}

if (typeDeclar.AttributeLists.Count == 0)
{
return false;
}

return true;
}

public void Initialize(GeneratorInitializationContext context)
static TypeDeclarationSyntax GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
{
// No initialization required for this one
return GetSemanticClassOrStruct(context);
}

static TypeDeclarationSyntax GetSemanticClassOrStruct(GeneratorSyntaxContext context)
{
if (!(context.Node is ClassDeclarationSyntax) && !(context.Node is StructDeclarationSyntax))
{
return null;
}

var typeDeclarationSyntax = (TypeDeclarationSyntax)context.Node;
foreach (var attributeListSyntax in typeDeclarationSyntax.AttributeLists)
{
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
{
IMethodSymbol attributeSymbol = context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol as IMethodSymbol;
if (attributeSymbol == null)
{
continue;
}

INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType;

if (attributeContainingTypeSymbol.ContainingNamespace.GetFullNamespace().StartsWith("StackMemoryCollections."))
{
return typeDeclarationSyntax;
}
}
}

return null;
}

private void Execute(Compilation compilation, ImmutableArray<TypeDeclarationSyntax> types, SourceProductionContext context)
{
//System.Diagnostics.Debugger.Launch();
var processor = new AttributeProcessor();
processor.FillAllTypes(compilation, types);
processor.Generate(context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class CommonHelpersGenerator
{
public void GenerateCommonHelpers(
in List<INamedTypeSymbol> typeHelpers,
in GeneratorExecutionContext context
in SourceProductionContext context
)
{
if (typeHelpers.Count == 0)
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/GenerateList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class ListGenerator

public void GenerateList(
in List<INamedTypeSymbol> typeList,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
)
{
Expand All @@ -29,7 +29,7 @@ public void GenerateList(
}

private void GenerateList(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in INamedTypeSymbol currentType,
in Model.TypeInfo typeInfo,
in string listNamespace
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/GenerateMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ internal class MemoryGenerator
private readonly StringBuilder _builder = new StringBuilder();

public void GenerateMemory(
in GeneratorExecutionContext context
in SourceProductionContext context
)
{
GenerateMemory(in context, "Class");
GenerateMemory(in context, "Struct");
}

private void GenerateMemory(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in string memoryNamespace
)
{
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/GenerateQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class QueueGenerator

public void GenerateQueue(
in List<INamedTypeSymbol> typeQueue,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
)
{
Expand All @@ -29,7 +29,7 @@ public void GenerateQueue(
}

private void GenerateQueue(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in INamedTypeSymbol currentType,
in Model.TypeInfo typeInfo,
in string queueNamespace
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/GenerateStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class StackGenerator

public void GenerateStack(
in List<INamedTypeSymbol> typeStack,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
)
{
Expand All @@ -29,7 +29,7 @@ public void GenerateStack(
}

private void GenerateStack(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in INamedTypeSymbol currentType,
in Model.TypeInfo typeInfo,
in string stackNamespace
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/GenerateWrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class WrappersGenerator

public void GenerateWrappers(
in List<INamedTypeSymbol> typeWrappers,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
)
{
Expand All @@ -30,7 +30,7 @@ public void GenerateWrappers(

private void GenerateWrapper(
in INamedTypeSymbol currentType,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Model.TypeInfo typeInfo,
in string wrapperNamespace,
in Dictionary<string, Model.TypeInfo> typeInfos
Expand Down
4 changes: 2 additions & 2 deletions Src/StackMemoryCollections/Generators/HelpersGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal class HelpersGenerator

public void GenerateHelpers(
in List<INamedTypeSymbol> typeHelpers,
in GeneratorExecutionContext context,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
)
{
Expand All @@ -26,7 +26,7 @@ public void GenerateHelpers(
private void GenerateHelpersForType(
INamedTypeSymbol currentType,
Dictionary<string, Model.TypeInfo> typeInfos,
GeneratorExecutionContext context
SourceProductionContext context
)
{
_builder.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal class PrimitiveListGenerator
private readonly StringBuilder _builder = new StringBuilder();

public void GeneratePrimitiveList(
in GeneratorExecutionContext context
in SourceProductionContext context
)
{
GenerateList<IntPtr>(context, 0, true);
Expand All @@ -34,7 +34,7 @@ in GeneratorExecutionContext context
}

private void GenerateList<T>(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in int sizeOf,
bool calculateSize
) where T : unmanaged
Expand All @@ -46,7 +46,7 @@ bool calculateSize
}

private void GeneratePrimitiveList<T>(
in GeneratorExecutionContext context,
in SourceProductionContext context,
in string ListNamespace,
in int sizeOf,
in string sizeOfStr,
Expand Down
Loading

0 comments on commit e704aa1

Please sign in to comment.