Merge pull request #18 from mlemanczyk/codex/stworz-generator-kodu-zrodowego-w-c#
Mark version increments for source generation
This commit is contained in:
7 files changed
+262
-10
No files matched your search
@@ -2,7 +2,8 @@
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Nullable>enable</Nullable>
|
||||
<DefineConstants>$(DefineConstants);WITH_VERSIONING</DefineConstants>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Recyclable.Collections</PackageId>
|
||||
<PackageVersion>0.0.6</PackageVersion>
|
||||
@@ -30,8 +31,12 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.5" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.5" />
|
||||
<PackageReference Include="morelinq" Version="3.4.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VersionedCollectionsGenerator\VersionedCollectionsGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -126,8 +126,9 @@ namespace Recyclable.Collections
|
||||
list._count = currentItemsCount;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void AddRange<T>(this RecyclableList<T> list, in Array items)
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
[VersionedCollectionsGenerator.RewriteForVersioned]
|
||||
public static void AddRange<T>(this RecyclableList<T> list, in Array items)
|
||||
{
|
||||
if (list._capacity < list._count + items.Length)
|
||||
{
|
||||
@@ -136,7 +137,9 @@ namespace Recyclable.Collections
|
||||
|
||||
Array.Copy(items, items.GetLowerBound(0), list._memoryBlock, list._count, items.Length);
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -149,7 +152,9 @@ namespace Recyclable.Collections
|
||||
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(list._memoryBlock, list._count, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -162,7 +167,9 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(new Span<T>(list._memoryBlock, list._count, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -175,7 +182,9 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(new Span<T>(list._memoryBlock, list._count, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -188,7 +197,9 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(list._memoryBlock, list._count);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -201,7 +212,9 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(list._memoryBlock, list._count);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -214,7 +227,9 @@ namespace Recyclable.Collections
|
||||
|
||||
items.CopyTo(list._memoryBlock, list._count);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -227,7 +242,9 @@ namespace Recyclable.Collections
|
||||
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new Span<T>(list._memoryBlock, list._count, items._count));
|
||||
list._count += items._count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -278,7 +295,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -309,7 +328,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -349,7 +370,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -372,7 +395,9 @@ namespace Recyclable.Collections
|
||||
new ReadOnlySpan<T>(items._items, 0, sourceCount).CopyTo(new Span<T>(list._memoryBlock, oldCount, sourceCount));
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -411,7 +436,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -434,7 +461,9 @@ namespace Recyclable.Collections
|
||||
new ReadOnlySpan<T>(items._heap, 0, sourceCount).CopyTo(new Span<T>(list._memoryBlock, oldCount, sourceCount));
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -473,7 +502,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -505,7 +536,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -532,7 +565,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static IEnumerator AddRange<T>(this RecyclableList<T> list, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
@@ -656,12 +691,16 @@ namespace Recyclable.Collections
|
||||
else if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity) && requiredAdditionalCapacity != 0)
|
||||
{
|
||||
AddRangeWithKnownCount(list, items, list._count, requiredAdditionalCapacity);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRangeEnumerated(list, items, growByCount);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count += requiredAdditionalCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -94,7 +96,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
Array.Copy(items, items.GetLowerBound(0), memoryBlock, index, items.Length);
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -109,7 +113,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -124,7 +130,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -139,7 +147,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
items.CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -154,7 +164,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -169,7 +181,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(list._memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -184,7 +198,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
items.CopyTo(memoryBlock, index);
|
||||
list._count += items.Count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -199,7 +215,9 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count));
|
||||
list._count += items._count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -251,7 +269,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count = targetCapacity;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static IEnumerator InsertRange<T>(this RecyclableList<T> list, int index, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
|
||||
@@ -101,7 +101,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count -= foundItemsCount;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
return foundItemsCount;
|
||||
}
|
||||
|
||||
@@ -125,43 +127,57 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
list._count -= count;
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, 0, list._count);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Reverse<T>(this RecyclableList<T> list, int index, int count)
|
||||
{
|
||||
Array.Reverse(list._memoryBlock, index, count);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, Comparison<T> comparison)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, new ComparisonToComparerAdapter<T>(comparison));
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, 0, list._count, comparer);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Sort<T>(this RecyclableList<T> list, int index, int count, IComparer<T>? comparer)
|
||||
{
|
||||
Array.Sort(list._memoryBlock, index, count, comparer);
|
||||
#if WITH_VERSIONING
|
||||
list._version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static T[] ToArray<T>(this RecyclableList<T> list)
|
||||
|
||||
@@ -5,8 +5,9 @@ using Recyclable.Collections.Pools;
|
||||
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
[Serializable]
|
||||
public sealed partial class RecyclableList<T> : IList<T>, IReadOnlyList<T>, IDisposable
|
||||
[Serializable]
|
||||
[VersionedCollectionsGenerator.GenerateVersioned]
|
||||
public sealed partial class RecyclableList<T> : IList<T>, IReadOnlyList<T>, IDisposable
|
||||
{
|
||||
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||
|
||||
@@ -17,7 +18,8 @@ namespace Recyclable.Collections
|
||||
#nullable restore
|
||||
|
||||
internal ulong _version;
|
||||
public ulong Version => _version;
|
||||
[VersionedCollectionsGenerator.CloneForVersioned]
|
||||
public ulong Version => _version;
|
||||
|
||||
public RecyclableList()
|
||||
{
|
||||
@@ -172,7 +174,9 @@ namespace Recyclable.Collections
|
||||
set
|
||||
{
|
||||
_memoryBlock[index] = value;
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +189,9 @@ namespace Recyclable.Collections
|
||||
if (_capacity != value)
|
||||
{
|
||||
_capacity = RecyclableListHelpers<T>.EnsureCapacity(this, _count, checked((int)BitOperations.RoundUpToPowerOf2((uint)value)));
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,7 +210,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_count = value;
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +251,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_memoryBlock[_count++] = item;
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
public T[] AsArray => _memoryBlock;
|
||||
@@ -262,7 +272,9 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
_count = 0;
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -295,7 +307,9 @@ namespace Recyclable.Collections
|
||||
|
||||
_memoryBlock[index] = item;
|
||||
_count++;
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -315,7 +329,9 @@ namespace Recyclable.Collections
|
||||
_memoryBlock[_count] = default;
|
||||
}
|
||||
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -342,7 +358,9 @@ namespace Recyclable.Collections
|
||||
_memoryBlock[_count] = default;
|
||||
}
|
||||
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -356,7 +374,9 @@ namespace Recyclable.Collections
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
#if WITH_VERSIONING
|
||||
_version++;
|
||||
#endif
|
||||
if (_count != 0)
|
||||
{
|
||||
if (_needsClearing)
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace VersionedCollectionsGenerator
|
||||
{
|
||||
[Generator]
|
||||
public sealed class VersionedCollectionsGenerator : ISourceGenerator
|
||||
{
|
||||
private const string AttributeText = """
|
||||
using System;
|
||||
|
||||
namespace VersionedCollectionsGenerator
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class GenerateVersionedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class CloneForVersionedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
|
||||
internal sealed class RewriteForVersionedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
|
||||
}
|
||||
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
context.AddSource("GenerateVersionedAttribute.g.cs", SourceText.From(AttributeText, Encoding.UTF8));
|
||||
|
||||
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var candidate in receiver.Candidates)
|
||||
{
|
||||
var model = context.Compilation.GetSemanticModel(candidate.SyntaxTree);
|
||||
var symbol = model.GetDeclaredSymbol(candidate) as INamedTypeSymbol;
|
||||
if (symbol is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!symbol.GetAttributes().Any(a => a.AttributeClass?.ToDisplayString() == "VersionedCollectionsGenerator.GenerateVersionedAttribute"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string originalName = symbol.Name;
|
||||
string newName = $"{originalName}Versioned";
|
||||
|
||||
var partials = GetAllPartials(context.Compilation, originalName);
|
||||
int index = 0;
|
||||
foreach (var partial in partials)
|
||||
{
|
||||
var tree = partial.SyntaxTree;
|
||||
var root = tree.GetRoot();
|
||||
var rewriter = new RenameRewriter(originalName, newName);
|
||||
var newRoot = rewriter.Visit(root);
|
||||
var text = newRoot.ToFullString()
|
||||
.Replace("#if WITH_VERSIONING", string.Empty)
|
||||
.Replace("#endif", string.Empty);
|
||||
context.AddSource($"{newName}_{index++}.g.cs", SourceText.From(text, Encoding.UTF8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<ClassDeclarationSyntax> GetAllPartials(Compilation compilation, string className)
|
||||
{
|
||||
foreach (var tree in compilation.SyntaxTrees)
|
||||
{
|
||||
var root = tree.GetRoot();
|
||||
foreach (var cls in root.DescendantNodes().OfType<ClassDeclarationSyntax>())
|
||||
{
|
||||
if (cls.Identifier.ValueText == className)
|
||||
{
|
||||
yield return cls;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class RenameRewriter : CSharpSyntaxRewriter
|
||||
{
|
||||
private readonly string _oldName;
|
||||
private readonly string _newName;
|
||||
|
||||
public RenameRewriter(string oldName, string newName)
|
||||
{
|
||||
_oldName = oldName;
|
||||
_newName = newName;
|
||||
}
|
||||
|
||||
public override SyntaxToken VisitToken(SyntaxToken token)
|
||||
{
|
||||
if (token.ValueText == _oldName)
|
||||
{
|
||||
return SyntaxFactory.Identifier(token.LeadingTrivia, _newName, token.TrailingTrivia);
|
||||
}
|
||||
|
||||
return base.VisitToken(token);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class SyntaxReceiver : ISyntaxReceiver
|
||||
{
|
||||
public List<ClassDeclarationSyntax> Candidates { get; } = new();
|
||||
|
||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||
{
|
||||
if (syntaxNode is ClassDeclarationSyntax classDecl && classDecl.AttributeLists.Count > 0)
|
||||
{
|
||||
Candidates.Add(classDecl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<EnforceExtendedAnalyzerRules>True</EnforceExtendedAnalyzerRules>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in new issue
Block a user