Skip to content

Commit

Permalink
feat:
Browse files Browse the repository at this point in the history
++ Do not regenerate code if the file containing the class with the attribute has not been changed. Previously, the code was regenerated whenever any change was made to any project file.
++ Use SourceProductionContext.CancellationToken

Resolve #53
  • Loading branch information
SoftStoneDevelop committed Sep 14, 2023
1 parent 160b51e commit 06141bd
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 37 deletions.
43 changes: 22 additions & 21 deletions Src/StackMemoryCollections/AttributeProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -32,17 +33,18 @@ internal class AttributeProcessor
private readonly List<INamedTypeSymbol> _typeGeneratedList = new List<INamedTypeSymbol>();
private readonly List<INamedTypeSymbol> _typeGeneratedQueue = new List<INamedTypeSymbol>();
private readonly List<INamedTypeSymbol> _typeGeneratedDictionary = new List<INamedTypeSymbol>();
private bool _containCollections = false;

private readonly Dictionary<string, Model.TypeInfo> _typeInfos = new Dictionary<string, Model.TypeInfo>();

public void FillAllTypes(
Compilation compilation,
ImmutableArray<TypeDeclarationSyntax> types
ImmutableArray<TypeDeclarationSyntax> types,
CancellationToken cancellationToken
)
{
foreach (var typeDeclaration in types )
{
cancellationToken.ThrowIfCancellationRequested();
var type = compilation.GetSemanticModel(typeDeclaration.SyntaxTree).GetDeclaredSymbol(typeDeclaration);

var attributes = type.GetAttributes();
Expand Down Expand Up @@ -84,18 +86,20 @@ ImmutableArray<TypeDeclarationSyntax> types
}
}

FillInfos();
FillInfos(cancellationToken);
}

private void FillInfos()
private void FillInfos(CancellationToken cancellationToken)
{
for (int i = 0; i < _typeHelpers.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var stackCurrentTypes = new Stack<INamedTypeSymbol>();
stackCurrentTypes.Push(_typeHelpers[i]);

while (stackCurrentTypes.Count != 0)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = stackCurrentTypes.Peek();
if (!currentType.Constructors.Any(an => an.Parameters.Length == 0))
{
Expand Down Expand Up @@ -393,24 +397,21 @@ private bool HelperMustGenerated(in System.Collections.Immutable.ImmutableArray<
);
}

public void Generate(SourceProductionContext context)
public void Generate(SourceProductionContext context, CancellationToken cancellationToken)
{
if (!_containCollections)
{
_primitiveWrappersGenerator.GeneratePrimitiveWrappers(context);
_primitiveStackGenerator.GeneratePrimitiveStack(context);
_primitiveQueueGenerator.GeneratePrimitiveQueue(context);
_primitiveListGenerator.GeneratePrimitiveList(context);
_memoryGenerator.GenerateMemory(context);
}

_commonHelpersHenerator.GenerateCommonHelpers(_typeHelpers, context);
_helpersGenerator.GenerateHelpers(in _typeHelpers, in context, in _typeInfos);

_wrappersGenerator.GenerateWrappers(in _typeWrappers, in context, in _typeInfos);
_stackGenerator.GenerateStack(in _typeGeneratedStack, in context, _typeInfos);
_queueGenerator.GenerateQueue(in _typeGeneratedQueue, in context, _typeInfos);
_listGenerator.GenerateList(in _typeGeneratedList, in context, _typeInfos);
_primitiveWrappersGenerator.GeneratePrimitiveWrappers(context, cancellationToken);
_primitiveStackGenerator.GeneratePrimitiveStack(context, cancellationToken);
_primitiveQueueGenerator.GeneratePrimitiveQueue(context, cancellationToken);
_primitiveListGenerator.GeneratePrimitiveList(context, cancellationToken);
_memoryGenerator.GenerateMemory(context, cancellationToken);

_commonHelpersHenerator.GenerateCommonHelpers(_typeHelpers, context, cancellationToken);
_helpersGenerator.GenerateHelpers(in _typeHelpers, in context, in _typeInfos, cancellationToken);

_wrappersGenerator.GenerateWrappers(in _typeWrappers, in context, in _typeInfos, cancellationToken);
_stackGenerator.GenerateStack(in _typeGeneratedStack, in context, _typeInfos, cancellationToken);
_queueGenerator.GenerateQueue(in _typeGeneratedQueue, in context, _typeInfos, cancellationToken);
_listGenerator.GenerateList(in _typeGeneratedList, in context, _typeInfos, cancellationToken);
}
}
}
35 changes: 31 additions & 4 deletions Src/StackMemoryCollections/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using StackMemoryCollections.Helpers;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

Expand All @@ -10,16 +11,37 @@ namespace StackMemoryCollections
[Generator]
public partial class Generator : IIncrementalGenerator
{
public class ByArrayComparer : IEqualityComparer<(Compilation compilation, ImmutableArray<TypeDeclarationSyntax> Nodes)>
{
public bool Equals(
(Compilation compilation, ImmutableArray<TypeDeclarationSyntax> Nodes) x,
(Compilation compilation, ImmutableArray<TypeDeclarationSyntax> Nodes) y)
{
return x.Nodes.Equals(y.Nodes);
}

public int GetHashCode((Compilation compilation, ImmutableArray<TypeDeclarationSyntax> Nodes) obj)
{
return obj.Nodes.GetHashCode();
}
}

public void Initialize(IncrementalGeneratorInitializationContext context)
{
//System.Diagnostics.Debugger.Launch();
var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (s, _) => IsSyntaxTargetForGeneration(s),
transform: (ctx, _) => GetSemanticTargetForGeneration(ctx))
.Where(m => m != null);
.Where(m => m != null)
.Collect()
.Select((sel, _) => sel.Distinct().ToImmutableArray())
;

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

context.RegisterSourceOutput(compilationAndClasses,
(spc, source) => Execute(source.Item1, source.Item2, spc));
Expand Down Expand Up @@ -94,9 +116,14 @@ static TypeDeclarationSyntax GetSemanticClassOrStruct(GeneratorSyntaxContext con
private void Execute(Compilation compilation, ImmutableArray<TypeDeclarationSyntax> types, SourceProductionContext context)
{
//System.Diagnostics.Debugger.Launch();
if (types.IsDefaultOrEmpty)
{
return;
}

var processor = new AttributeProcessor();
processor.FillAllTypes(compilation, types);
processor.Generate(context);
processor.FillAllTypes(compilation, types, context.CancellationToken);
processor.Generate(context, context.CancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Threading;

namespace StackMemoryCollections
{
public class CommonHelpersGenerator
{
public void GenerateCommonHelpers(
in List<INamedTypeSymbol> typeHelpers,
in SourceProductionContext context
in SourceProductionContext context,
CancellationToken cancellationToken
)
{
cancellationToken.ThrowIfCancellationRequested();
if (typeHelpers.Count == 0)
{
return;
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/GenerateList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -12,11 +13,13 @@ internal class ListGenerator
public void GenerateList(
in List<INamedTypeSymbol> typeList,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
in Dictionary<string, Model.TypeInfo> typeInfos,
CancellationToken cancellationToken
)
{
for (int i = 0; i < typeList.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = typeList[i];
if (!typeInfos.TryGetValue($"{currentType.ContainingNamespace}.{currentType.Name}", out var typeInfo))
{
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/GenerateMemory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -8,9 +9,11 @@ internal class MemoryGenerator
private readonly StringBuilder _builder = new StringBuilder();

public void GenerateMemory(
in SourceProductionContext context
in SourceProductionContext context,
CancellationToken cancellationToken
)
{
cancellationToken.ThrowIfCancellationRequested();
GenerateMemory(in context, "Class");
GenerateMemory(in context, "Struct");
}
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/GenerateQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -12,11 +13,13 @@ internal class QueueGenerator
public void GenerateQueue(
in List<INamedTypeSymbol> typeQueue,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
in Dictionary<string, Model.TypeInfo> typeInfos,
CancellationToken cancellationToken
)
{
for (int i = 0; i < typeQueue.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = typeQueue[i];
if (!typeInfos.TryGetValue($"{currentType.ContainingNamespace}.{currentType.Name}", out var typeInfo))
{
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/GenerateStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -12,11 +13,13 @@ internal class StackGenerator
public void GenerateStack(
in List<INamedTypeSymbol> typeStack,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
in Dictionary<string, Model.TypeInfo> typeInfos,
CancellationToken cancellationToken
)
{
for (int i = 0; i < typeStack.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = typeStack[i];
if (!typeInfos.TryGetValue($"{currentType.ContainingNamespace}.{currentType.Name}", out var typeInfo))
{
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/GenerateWrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -12,11 +13,13 @@ internal class WrappersGenerator
public void GenerateWrappers(
in List<INamedTypeSymbol> typeWrappers,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
in Dictionary<string, Model.TypeInfo> typeInfos,
CancellationToken cancellationToken
)
{
for (int i = 0; i < typeWrappers.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = typeWrappers[i];
if (!typeInfos.TryGetValue($"{currentType.ContainingNamespace}.{currentType.Name}", out var typeInfo))
{
Expand Down
5 changes: 4 additions & 1 deletion Src/StackMemoryCollections/Generators/HelpersGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace StackMemoryCollections
{
Expand All @@ -13,11 +14,13 @@ internal class HelpersGenerator
public void GenerateHelpers(
in List<INamedTypeSymbol> typeHelpers,
in SourceProductionContext context,
in Dictionary<string, Model.TypeInfo> typeInfos
in Dictionary<string, Model.TypeInfo> typeInfos,
CancellationToken cancellationToken
)
{
for (int i = 0; i < typeHelpers.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var currentType = typeHelpers[i];
GenerateHelpersForType(currentType, typeInfos, context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis;
using System;
using System.Text;
using System.Threading;

namespace StackMemoryCollections.Generators.Primitive
{
Expand All @@ -9,23 +10,30 @@ internal class PrimitiveListGenerator
private readonly StringBuilder _builder = new StringBuilder();

public void GeneratePrimitiveList(
in SourceProductionContext context
in SourceProductionContext context,
CancellationToken cancellationToken
)
{
cancellationToken.ThrowIfCancellationRequested();
GenerateList<IntPtr>(context, 0, true);

cancellationToken.ThrowIfCancellationRequested();
GenerateList<int>(context, 4, false);
GenerateList<uint>(context, 4, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateList<long>(context, 8, false);
GenerateList<ulong>(context, 8, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateList<sbyte>(context, 1, false);
GenerateList<byte>(context, 1, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateList<short>(context, 2, false);
GenerateList<ushort>(context, 2, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateList<char>(context, 2, false);
GenerateList<decimal>(context, 16, false);
GenerateList<double>(context, 8, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis;
using System;
using System.Text;
using System.Threading;

namespace StackMemoryCollections.Generators.Primitive
{
Expand All @@ -9,25 +10,33 @@ internal class PrimitiveQueueGenerator
private readonly StringBuilder _builder = new StringBuilder();

public void GeneratePrimitiveQueue(
in SourceProductionContext context
in SourceProductionContext context,
CancellationToken cancellationToken
)
{
cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<IntPtr>(in context, 0, true);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<int>(in context, 4, false);
GenerateQueue<uint>(in context, 4, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<long>(in context, 8, false);
GenerateQueue<ulong>(in context, 8, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<sbyte>(in context, 1, false);
GenerateQueue<byte>(in context, 1, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<short>(in context, 2, false);
GenerateQueue<ushort>(in context, 2, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<char>(in context, 2, false);

cancellationToken.ThrowIfCancellationRequested();
GenerateQueue<decimal>(in context, 16, false);
GenerateQueue<double>(in context, 8, false);
GenerateQueue<bool>(in context, 1, false);//1 byte is not optimal
Expand Down
Loading

0 comments on commit 06141bd

Please sign in to comment.