mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-05 06:27:21 +00:00
Moved all extension methods into extension blocks (#1155)
This commit is contained in:
1 parent
acc7d09fa2
commit
c0a75f39ac
138 files changed
+5884
-4954
No files matched your search
@@ -0,0 +1,69 @@
|
||||
using AIStudio.Tests.Models.Generation;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
using SourceCodeRules.StyleAnalyzers;
|
||||
|
||||
namespace AIStudio.Tests.Analyzers;
|
||||
|
||||
/// <summary>
|
||||
/// Checks that extension methods are declared in extension blocks, not with a this parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// AI Studio declares all its extension members in extension blocks, one per receiver. MWAIS0016 refuses the
|
||||
/// classic form while compiling, except for a method with a params parameter: for a member of an extension
|
||||
/// block, the compiler of the .NET 10.0.1xx SDK warns about every argument passed one by one to a params
|
||||
/// parameter (CS8620, dotnet/roslyn#80024).
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public sealed class ClassicExtensionMethodAnalyzerTests
|
||||
{
|
||||
[TestCase("public static string Label(this Meeting meeting) => meeting.Name;", "Label", TestName = "A public extension method")]
|
||||
[TestCase("private static string Label(this Meeting meeting) => meeting.Name;", "Label", TestName = "A private extension method")]
|
||||
[TestCase("public static string Label(this Meeting meeting, string prefix) => prefix + meeting.Name;", "Label", TestName = "An extension method with further parameters")]
|
||||
[TestCase("public static T Echo<T>(this T value) where T : class => value;", "Echo", TestName = "A generic extension method")]
|
||||
[TestCase("public static void Bump(this ref int value) => value++;", "Bump", TestName = "An extension method with a ref receiver")]
|
||||
[TestCase("public static System.Threading.Tasks.Task<string> LabelAsync(this Meeting meeting) => System.Threading.Tasks.Task.FromResult(meeting.Name);", "LabelAsync", TestName = "An asynchronous extension method")]
|
||||
public async Task AClassicExtensionMethodIsRefused(string member, string name)
|
||||
{
|
||||
var reported = await AnalyzeAsync(member);
|
||||
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(reported, Has.Count.EqualTo(1));
|
||||
Assert.That(reported.FirstOrDefault()?.Id, Is.EqualTo("MWAIS0016"));
|
||||
Assert.That(reported.FirstOrDefault()?.GetMessage(), Does.Contain($"'{name}'"));
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("extension(Meeting meeting) { public string Label() => meeting.Name; }", TestName = "A member of an extension block")]
|
||||
[TestCase("extension<T>(T value) where T : class { public T Echo() => value; }", TestName = "A member of a generic extension block")]
|
||||
[TestCase("public static string Label(Meeting meeting) => meeting.Name;", TestName = "A static method without a this parameter")]
|
||||
[TestCase("public static string Label(this Meeting meeting, params string[] prefixes) => string.Concat(prefixes) + meeting.Name;", TestName = "An extension method with a params parameter")]
|
||||
public async Task AnythingElseIsLeftAlone(string member)
|
||||
{
|
||||
var reported = await AnalyzeAsync(member);
|
||||
|
||||
Assert.That(reported, Is.Empty);
|
||||
}
|
||||
|
||||
private static async Task<IReadOnlyList<Diagnostic>> AnalyzeAsync(string member)
|
||||
{
|
||||
var source =
|
||||
$$"""
|
||||
namespace Sample;
|
||||
|
||||
public sealed class Meeting
|
||||
{
|
||||
public string Name { get; set; } = "Kickoff";
|
||||
}
|
||||
|
||||
public static class MeetingExtensions
|
||||
{
|
||||
{{member}}
|
||||
}
|
||||
""";
|
||||
|
||||
return await CompilationHarness.AnalyzeAsync(source, new ClassicExtensionMethodAnalyzer());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user