Skip to content

Commit

Permalink
Add first version of selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
Enterprize1 committed Aug 29, 2024
1 parent 1486a2b commit c865e57
Show file tree
Hide file tree
Showing 44 changed files with 2,646 additions and 4 deletions.
30 changes: 30 additions & 0 deletions src/Fluss.Regen/Fluss.Regen.Tests/Fluss.Regen.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<RootNamespace>Fluss.Regen.Tests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="1.1.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2"/>
<PackageReference Include="Snapshooter.Xunit" Version="0.14.1" />
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Fluss.Regen\Fluss.Regen.csproj"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="DiffPlex" Version="1.7.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Fluss.Regen.Tests.Utils.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;

namespace Fluss.Regen.Tests;

public class SampleIncrementalSourceGeneratorTests
{
[Fact]
public void GeneratesForNonAsyncSelector()
{
var generator = new AutoLoadGenerator();

var driver = CSharpGeneratorDriver.Create(generator);

var compilation = CSharpCompilation.Create(nameof(SampleIncrementalSourceGeneratorTests),
[CSharpSyntaxTree.ParseText(
@"
using Fluss.Regen;
namespace TestNamespace;
public class Test
{
[Selector]
public static int Add(int a, int b) {
return a + b;
}
}")],
new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
});

var runResult = driver.RunGenerators(compilation).GetRunResult();

runResult.MatchMarkdownSnapshot();
}

[Fact]
public void GeneratesForAsyncSelector()
{
var generator = new AutoLoadGenerator();

var driver = CSharpGeneratorDriver.Create(generator);

var compilation = CSharpCompilation.Create(nameof(SampleIncrementalSourceGeneratorTests),
[CSharpSyntaxTree.ParseText(
@"
using Fluss.Regen;
using System.Threading.Tasks;
namespace TestNamespace;
public class Test
{
[Selector]
public static async ValueTask<int> Add(int a, int b) {
return a + b;
}
[Selector]
public static async ValueTask<int> Add2(int a, int b) {
return a + b;
}
}")],
new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
});

var runResult = driver.RunGenerators(compilation).GetRunResult();

runResult.MatchMarkdownSnapshot();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Globalization;
using System.Reflection;

namespace Fluss.Regen.Tests.Utils.Extensions;

/// <summary>
/// The method base extension is used to add more functionality
/// to the class <see cref="MethodBase"/>
/// </summary>
internal static class MethodBaseExtension
{
/// <summary>
/// Creates the name of the method with class name.
/// </summary>
/// <param name="methodBase">The used method name to get the name.</param>
public static string ToName(this MethodBase methodBase)
=> string.Concat(
methodBase.ReflectedType!.Name.ToString(CultureInfo.InvariantCulture), ".",
methodBase.Name.ToString(CultureInfo.InvariantCulture), ".snap");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Fluss.Regen.Tests.Utils.Formatters;

namespace Fluss.Regen.Tests.Utils.Extensions;

public static class SnapshotExtensions
{
public static void MatchInlineSnapshot(
this object? value,
string snapshot,
ISnapshotValueFormatter? formatter = null)
=> Snapshot.Create().Add(value, formatter: formatter).MatchInline(snapshot);

public static void MatchSnapshot(this Snapshot value)
=> value.Match();

public static void MatchSnapshot(
this object? value,
object? postFix = null,
string? extension = null,
ISnapshotValueFormatter? formatter = null)
=> Snapshot.Match(value, postFix?.ToString(), extension, formatter);

public static void MatchMarkdownSnapshot(
this object? value,
object? postFix = null,
string? extension = null,
ISnapshotValueFormatter? formatter = null)
=> Snapshot.Create(postFix?.ToString(), extension).Add(value, formatter: formatter).MatchMarkdown();

public static void MatchMarkdownSnapshot(this Snapshot value)
=> value.MatchMarkdown();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;

namespace Fluss.Regen.Tests.Utils.Extensions;

/// <summary>
/// Some extensions for Type, to support snapshot testing.
/// </summary>
internal static class TypeExtensions
{
/// <summary>
/// Returns the list of inherited types.
/// </summary>
/// <param name="type">The current object type.</param>
/// <returns>The list of all inherited types.</returns>
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
var current = type;

while (current != null)
{
yield return current;
current = current.BaseType;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Buffers;
using System.Text;

namespace Fluss.Regen.Tests.Utils.Extensions;

public static class WriterExtensions
{
private static readonly Encoding _utf8 = Encoding.UTF8;

public static void Append(this IBufferWriter<byte> snapshot, string value)
=> Append(snapshot, value.AsSpan());

public static void Append(this IBufferWriter<byte> snapshot, ReadOnlySpan<char> value)
{
_utf8.GetBytes(value, snapshot);
}

public static void AppendLine(this IBufferWriter<byte> snapshot)
{
snapshot.GetSpan(1)[0] = (byte)'\n';
snapshot.Advance(1);
}

public static void AppendLine(this IBufferWriter<byte> snapshot, bool appendWhenTrue)
{
if (!appendWhenTrue)
{
return;
}

snapshot.GetSpan(1)[0] = (byte)'\n';
snapshot.Advance(1);
}

public static void AppendSeparator(this IBufferWriter<byte> snapshot)
{
const byte hyphen = (byte)'-';
var span = snapshot.GetSpan(15);

for(var i = 0; i < 15; i++)
{
span[i] = hyphen;
}

snapshot.Advance(15);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Buffers;
using Fluss.Regen.Tests.Utils.Extensions;

namespace Fluss.Regen.Tests.Utils.Formatters;

public class ExceptionSnapshotValueFormatter : SnapshotValueFormatter<Exception>
{
protected override void Format(IBufferWriter<byte> snapshot, Exception value)
{
snapshot.Append(value.GetType().FullName ?? value.GetType().Name);
snapshot.AppendLine();
snapshot.Append(value.Message);
snapshot.AppendLine();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Buffers;
using Fluss.Regen.Tests.Utils.Extensions;
using Microsoft.CodeAnalysis;

namespace Fluss.Regen.Tests.Utils.Formatters;

public class GeneratorDriverRunResultSnapshotValueFormatter : SnapshotValueFormatter<GeneratorDriverRunResult>
{
protected override void Format(IBufferWriter<byte> snapshot, GeneratorDriverRunResult value)
{
throw new NotImplementedException();
}

protected override void FormatMarkdown(IBufferWriter<byte> snapshot, GeneratorDriverRunResult value)
{
foreach (var tree in value.GeneratedTrees)
{
snapshot.Append($"## {tree.FilePath}");
snapshot.AppendLine();
snapshot.Append("```csharp");
snapshot.AppendLine();
snapshot.Append(tree.GetText().ToString());
snapshot.AppendLine();
snapshot.Append("```");
snapshot.AppendLine();
snapshot.AppendLine();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Buffers;
using System.Linq;
using System.Net.Http;
using Fluss.Regen.Tests.Utils.Extensions;

namespace Fluss.Regen.Tests.Utils.Formatters;

public class HttpResponseSnapshotValueFormatter : SnapshotValueFormatter<HttpResponseMessage>
{
protected override void Format(IBufferWriter<byte> snapshot, HttpResponseMessage value)
{
var first = true;

foreach (var header in value.Headers.Concat(value.Content.Headers))
{
if (first)
{
snapshot.Append("Headers:");
snapshot.AppendLine();
first = false;
}

snapshot.Append($"{header.Key}: {string.Join(" ", header.Value)}");
snapshot.AppendLine();
}

if (!first)
{
snapshot.Append("-------------------------->");
snapshot.AppendLine();
}

snapshot.Append($"Status Code: {value.StatusCode}");

snapshot.AppendLine();
snapshot.Append("-------------------------->");
snapshot.AppendLine();

snapshot.Append(value.Content.ReadAsStringAsync().Result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Buffers;

namespace Fluss.Regen.Tests.Utils.Formatters;

/// <summary>
/// Formats a snapshot segment value for the snapshot file.
/// </summary>
public interface IMarkdownSnapshotValueFormatter
{
/// <summary>
/// Specifies if the formatter can handle the snapshot segment value.
/// </summary>
/// <param name="value">
/// The snapshot segment value.
/// </param>
/// <returns>
/// <c>true</c> if the formatter can handle the snapshot segment value;
/// otherwise, <c>false</c>.
/// </returns>
bool CanHandle(object? value);

/// <summary>
/// Formats the specified snapshot segment value for the snapshot file.
/// </summary>
/// <param name="snapshot">
/// The snapshot file writer.
/// </param>
/// <param name="value">
/// The snapshot segment vale.
/// </param>
void FormatMarkdown(IBufferWriter<byte> snapshot, object? value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Buffers;

namespace Fluss.Regen.Tests.Utils.Formatters;

/// <summary>
/// Formats a snapshot segment value for the snapshot file.
/// </summary>
public interface ISnapshotValueFormatter
{
/// <summary>
/// Specifies if the formatter can handle the snapshot segment value.
/// </summary>
/// <param name="value">
/// The snapshot segment value.
/// </param>
/// <returns>
/// <c>true</c> if the formatter can handle the snapshot segment value;
/// otherwise, <c>false</c>.
/// </returns>
bool CanHandle(object? value);

/// <summary>
/// Formats the specified snapshot segment value for the snapshot file.
/// </summary>
/// <param name="snapshot">
/// The snapshot file writer.
/// </param>
/// <param name="value">
/// The snapshot segment vale.
/// </param>
void Format(IBufferWriter<byte> snapshot, object? value);
}
Loading

0 comments on commit c865e57

Please sign in to comment.