Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
#nullable enable

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Tests.TestData;

namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for ContainsMessage
/// </summary>
public sealed class StringArray_ContainsMessage_String_Bool_Assertion : Assertion<string[]>
{
private static readonly Task<AssertionResult> _passedTask = Task.FromResult(AssertionResult.Passed);

private readonly string _needle;
private readonly bool _exact;

public StringArray_ContainsMessage_String_Bool_Assertion(AssertionContext<string[]> context, string needle, bool exact)
: base(context)
{
_needle = needle;
_exact = exact;
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<string[]> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value!.ContainsMessage(_needle, _exact);
return result
? _passedTask
: Task.FromResult(AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return $"to contain message '{_needle}'";
}
}

public static partial class ArrayTargetAssertionExtensions
{
/// <summary>
/// Generated extension method for ContainsMessage
/// </summary>
public static StringArray_ContainsMessage_String_Bool_Assertion ContainsMessage(this IAssertionSource<string[]> source, string needle, bool exact, [CallerArgumentExpression(nameof(needle))] string? needleExpression = null, [CallerArgumentExpression(nameof(exact))] string? exactExpression = null)
{
source.Context.ExpressionBuilder.Append($".ContainsMessage({needleExpression}, {exactExpression})");
return new StringArray_ContainsMessage_String_Bool_Assertion(source.Context, needle, exact);
}

}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
#nullable enable

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Tests.TestData;

namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for ContainsMessage
/// </summary>
public sealed class StringArray_ContainsMessage_String_Bool_Assertion : Assertion<string[]>
{
private static readonly Task<AssertionResult> _passedTask = Task.FromResult(AssertionResult.Passed);

private readonly string _needle;
private readonly bool _exact;

public StringArray_ContainsMessage_String_Bool_Assertion(AssertionContext<string[]> context, string needle, bool exact)
: base(context)
{
_needle = needle;
_exact = exact;
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<string[]> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value!.ContainsMessage(_needle, _exact);
return result
? _passedTask
: Task.FromResult(AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return $"to contain message '{_needle}'";
}
}

public static partial class ArrayTargetAssertionExtensions
{
/// <summary>
/// Generated extension method for ContainsMessage
/// </summary>
public static StringArray_ContainsMessage_String_Bool_Assertion ContainsMessage(this IAssertionSource<string[]> source, string needle, bool exact, [CallerArgumentExpression(nameof(needle))] string? needleExpression = null, [CallerArgumentExpression(nameof(exact))] string? exactExpression = null)
{
source.Context.ExpressionBuilder.Append($".ContainsMessage({needleExpression}, {exactExpression})");
return new StringArray_ContainsMessage_String_Bool_Assertion(source.Context, needle, exact);
}

}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
#nullable enable

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Tests.TestData;

namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for ContainsMessage
/// </summary>
public sealed class StringArray_ContainsMessage_String_Bool_Assertion : Assertion<string[]>
{
private static readonly Task<AssertionResult> _passedTask = Task.FromResult(AssertionResult.Passed);

private readonly string _needle;
private readonly bool _exact;

public StringArray_ContainsMessage_String_Bool_Assertion(AssertionContext<string[]> context, string needle, bool exact)
: base(context)
{
_needle = needle;
_exact = exact;
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<string[]> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value!.ContainsMessage(_needle, _exact);
return result
? _passedTask
: Task.FromResult(AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return $"to contain message '{_needle}'";
}
}

public static partial class ArrayTargetAssertionExtensions
{
/// <summary>
/// Generated extension method for ContainsMessage
/// </summary>
public static StringArray_ContainsMessage_String_Bool_Assertion ContainsMessage(this IAssertionSource<string[]> source, string needle, bool exact, [CallerArgumentExpression(nameof(needle))] string? needleExpression = null, [CallerArgumentExpression(nameof(exact))] string? exactExpression = null)
{
source.Context.ExpressionBuilder.Append($".ContainsMessage({needleExpression}, {exactExpression})");
return new StringArray_ContainsMessage_String_Bool_Assertion(source.Context, needle, exact);
}

}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
#nullable enable

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using TUnit.Assertions.Core;
using TUnit.Assertions.Tests.TestData;

namespace TUnit.Assertions.Extensions;

/// <summary>
/// Generated assertion for ContainsMessage
/// </summary>
public sealed class StringArray_ContainsMessage_String_Bool_Assertion : Assertion<string[]>
{
private static readonly Task<AssertionResult> _passedTask = Task.FromResult(AssertionResult.Passed);

private readonly string _needle;
private readonly bool _exact;

public StringArray_ContainsMessage_String_Bool_Assertion(AssertionContext<string[]> context, string needle, bool exact)
: base(context)
{
_needle = needle;
_exact = exact;
}

protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<string[]> metadata)
{
var value = metadata.Value;
var exception = metadata.Exception;

if (exception != null)
{
return Task.FromResult(AssertionResult.Failed($"threw {exception.GetType().FullName}"));
}

if (value is null)
{
return Task.FromResult(AssertionResult.Failed("Actual value is null"));
}

var result = value!.ContainsMessage(_needle, _exact);
return result
? _passedTask
: Task.FromResult(AssertionResult.Failed($"found {value}"));
}

protected override string GetExpectation()
{
return $"to contain message '{_needle}'";
}
}

public static partial class ArrayTargetAssertionExtensions
{
/// <summary>
/// Generated extension method for ContainsMessage
/// </summary>
public static StringArray_ContainsMessage_String_Bool_Assertion ContainsMessage(this IAssertionSource<string[]> source, string needle, bool exact, [CallerArgumentExpression(nameof(needle))] string? needleExpression = null, [CallerArgumentExpression(nameof(exact))] string? exactExpression = null)
{
source.Context.ExpressionBuilder.Append($".ContainsMessage({needleExpression}, {exactExpression})");
return new StringArray_ContainsMessage_String_Bool_Assertion(source.Context, needle, exact);
}

}

]
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,21 @@ public Task RefStructParameter() => RunTest(
await Assert.That(mainFile).Contains("value!.Contains(_message)");
});
#endif

[Test]
public Task ArrayTargetType() => RunTest(
Path.Combine(Sourcy.Git.RootDirectory.FullName,
"TUnit.Assertions.SourceGenerator.Tests",
"TestData",
"ArrayTargetAssertion.cs"),
async generatedFiles =>
{
await Assert.That(generatedFiles).HasCount(1);

var mainFile = generatedFiles.FirstOrDefault(f => f.Contains("ContainsMessage"));
await Assert.That(mainFile).IsNotNull();
// Verify extension method targets IAssertionSource<string[]>
await Assert.That(mainFile!).Contains("IAssertionSource<string[]>");
await Assert.That(mainFile!).Contains("StringArray_ContainsMessage_String_Bool_Assertion");
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using TUnit.Assertions.Attributes;

namespace TUnit.Assertions.Tests.TestData;

/// <summary>
/// Test case: GenerateAssertion targeting a concrete array type (string[])
/// Should generate Assertion class and extension method using IAssertionSource&lt;string[]&gt;
/// </summary>
public static partial class ArrayTargetAssertionExtensions
{
[GenerateAssertion(ExpectationMessage = "to contain message '{needle}'")]
public static bool ContainsMessage(this string[] strings, string needle, bool exact = true)
{
return strings.Any(x => exact ? x == needle : x.Contains(needle));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
public static string BuildAssertion = "MethodAssertionData";

private static readonly DiagnosticDescriptor MethodMustBeStaticRule = new DiagnosticDescriptor(
id: "TUNITGEN001",

Check warning on line 23 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Włącz śledzenie wydań analizatora dla projektu analizatora zawierającego regułę „TUNITGEN001” (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 23 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN001' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 23 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN001' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 23 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN001' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 23 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN001' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
title: "Method must be static",
messageFormat: "Method '{0}' decorated with [GenerateAssertion] must be static",
category: "TUnit.Assertions.SourceGenerator",
Expand All @@ -29,7 +29,7 @@
description: "Methods decorated with [GenerateAssertion] must be static to be used in generated assertions.");

private static readonly DiagnosticDescriptor MethodMustHaveParametersRule = new DiagnosticDescriptor(
id: "TUNITGEN002",

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / integration-tests

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (fr-FR)

Activer le suivi de version d'analyseur pour le projet d'analyseur contenant la règle 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Włącz śledzenie wydań analizatora dla projektu analizatora zawierającego regułę „TUNITGEN002” (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Analyseversionsnachverfolgung für Analyseprojekt mit Regel "TUNITGEN002" aktivieren (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 32 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN002' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
title: "Method must have at least one parameter",
messageFormat: "Method '{0}' decorated with [GenerateAssertion] must have at least one parameter (the value to assert)",
category: "TUnit.Assertions.SourceGenerator",
Expand All @@ -38,18 +38,18 @@
description: "Methods decorated with [GenerateAssertion] must have at least one parameter representing the value being asserted.");

private static readonly DiagnosticDescriptor UnsupportedReturnTypeRule = new DiagnosticDescriptor(
id: "TUNITGEN003",

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / integration-tests

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Włącz śledzenie wydań analizatora dla projektu analizatora zawierającego regułę „TUNITGEN003” (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Analyseversionsnachverfolgung für Analyseprojekt mit Regel "TUNITGEN003" aktivieren (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 41 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
title: "Unsupported return type",
messageFormat: "Method '{0}' decorated with [GenerateAssertion] has unsupported return type '{1}'. Supported types are: bool, AssertionResult, Task<bool>, Task<AssertionResult>",

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / integration-tests

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (fr-FR)

Le message du diagnostic ne doit comporter aucun caractère de retour de ligne et aucun espace blanc de début ou de fin, et doit tenir en une seule phrase sans point final ou en plusieurs phrases avec un point final

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Komunikat dotyczący diagnostyki nie powinien zawierać znaku nowego wiersza ani odstępów na początku i końcu oraz powinien być pojedynczym zdaniem bez kropki na końcu lub wieloma zdaniami z kropkami na końcu

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Die Diagnosemeldung darf keine Zeilenvorschubzeichen und keine führenden oder nachfolgenden Leerzeichen enthalten und muss entweder einen einzelnen Satz ohne Satzendepunkt oder mehrere Sätze mit Satzendepunkt umfassen.

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 43 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period
category: "TUnit.Assertions.SourceGenerator",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: "Methods decorated with [GenerateAssertion] must return bool, AssertionResult, Task<bool>, or Task<AssertionResult>.");

private static readonly DiagnosticDescriptor RefStructRequiresInliningRule = new DiagnosticDescriptor(
id: "TUNITGEN004",

Check warning on line 50 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (fr-FR)

Activer le suivi de version d'analyseur pour le projet d'analyseur contenant la règle 'TUNITGEN004' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 50 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Analyseversionsnachverfolgung für Analyseprojekt mit Regel "TUNITGEN004" aktivieren (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 50 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN004' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 50 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Enable analyzer release tracking for the analyzer project containing rule 'TUNITGEN004' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
title: "Ref struct parameter requires method body inlining",
messageFormat: "Method '{0}' has ref struct parameter '{1}' of type '{2}'. Use InlineMethodBody = true and ensure the method has a single-expression or single-return-statement body",

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / integration-tests

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (fr-FR)

Le message du diagnostic ne doit comporter aucun caractère de retour de ligne et aucun espace blanc de début ou de fin, et doit tenir en une seule phrase sans point final ou en plusieurs phrases avec un point final

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Komunikat dotyczący diagnostyki nie powinien zawierać znaku nowego wiersza ani odstępów na początku i końcu oraz powinien być pojedynczym zdaniem bez kropki na końcu lub wieloma zdaniami z kropkami na końcu

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Die Diagnosemeldung darf keine Zeilenvorschubzeichen und keine führenden oder nachfolgenden Leerzeichen enthalten und muss entweder einen einzelnen Satz ohne Satzendepunkt oder mehrere Sätze mit Satzendepunkt umfassen.

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period

Check warning on line 52 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period
category: "TUnit.Assertions.SourceGenerator",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
Expand Down Expand Up @@ -825,7 +825,7 @@
// Add null-forgiving operator for reference types if not already present
// This is safe because we've already checked for null above
var isNullable = data.TargetType.IsNullable;
if (isNullable && !string.IsNullOrEmpty(inlinedBody) && !inlinedBody.StartsWith("value!"))

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / integration-tests

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (fr-FR)

Déréférencement d'une éventuelle référence null.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (pl-PL)

Wyłuskanie odwołania, które może mieć wartość null.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (de-DE)

Dereferenzierung eines möglichen Nullverweises.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (windows-latest)

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (ubuntu-latest)

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Dereference of a possibly null reference.

Check warning on line 828 in TUnit.Assertions.SourceGenerator/Generators/MethodAssertionGenerator.cs

View workflow job for this annotation

GitHub Actions / modularpipeline (macos-latest)

Dereference of a possibly null reference.
{
// Replace null-conditional operators with null-forgiving + regular operators
// value?.Member becomes value!.Member (safe because we already null-checked)
Expand Down Expand Up @@ -1026,6 +1026,12 @@

private static string GetSimpleTypeName(ITypeSymbol type)
{
// Handle array types: string[] becomes StringArray
if (type is IArrayTypeSymbol arrayType)
{
return $"{GetSimpleTypeName(arrayType.ElementType)}Array";
}

// Handle special types first
var simpleName = type.SpecialType switch
{
Expand Down
43 changes: 43 additions & 0 deletions TUnit.Assertions.Tests/GenerateAssertionArrayTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using TUnit.Assertions.Attributes;

namespace TUnit.Assertions.Tests;

/// <summary>
/// Tests that [GenerateAssertion] works correctly when targeting concrete array types.
/// The source generator creates an extension method on IAssertionSource&lt;string[]&gt;
/// and ArrayAssertion&lt;string&gt; (returned by Assert.That(string[])) implements that interface.
/// </summary>
public class GenerateAssertionArrayTests
{
[Test]
public async Task ContainsMessage_ExactMatch_Passes()
{
string[] items = ["food", "bard"];
await Assert.That(items).ContainsMessage("food", true);
}

[Test]
public async Task ContainsMessage_PartialMatch_Passes()
{
string[] items = ["food", "bard"];
await Assert.That(items).ContainsMessage("foo", false);
}

[Test]
public async Task ContainsMessage_NoMatch_Fails()
{
string[] items = ["food", "bard"];
var action = async () => await Assert.That(items).ContainsMessage("xyz", true);

await Assert.That(action).Throws<AssertionException>();
}
}

public static partial class GenerateAssertionArrayTestExtensions
{
[GenerateAssertion(ExpectationMessage = "to contain message '{needle}'")]
public static bool ContainsMessage(this string[] strings, string needle, bool exact = true)
{
return strings.Any(x => exact ? x == needle : x.Contains(needle));
}
}
7 changes: 4 additions & 3 deletions TUnit.Assertions/Extensions/Assert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,16 @@ public static ListAssertion<TItem> That<TItem>(

/// <summary>
/// Creates an assertion for an array value.
/// Arrays are routed to CollectionAssertion to preserve array-specific generated assertions.
/// Returns ArrayAssertion which implements IAssertionSource&lt;TItem[]&gt;,
/// enabling generated assertions that target concrete array types (e.g., string[]).
/// Example: await Assert.That(array).IsSingleElement();
/// </summary>
[OverloadResolutionPriority(5)]
public static CollectionAssertion<TItem> That<TItem>(
public static ArrayAssertion<TItem> That<TItem>(
TItem[]? value,
[CallerArgumentExpression(nameof(value))] string? expression = null)
{
return new CollectionAssertion<TItem>(value!, expression);
return new ArrayAssertion<TItem>(value, expression);
}

/// <summary>
Expand Down
Loading
Loading