Skip to content

Commit

Permalink
Find token from Xunit.TestContext.Current.CancellationToken
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Dec 22, 2024
1 parent 58436c3 commit aa97561
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private sealed class AnalyzerContext(Compilation compilation)
private INamedTypeSymbol? TaskOfTSymbol { get; } = compilation.GetBestTypeByMetadataName("System.Threading.Tasks.Task`1");
private INamedTypeSymbol? ConfiguredCancelableAsyncEnumerableSymbol { get; } = compilation.GetBestTypeByMetadataName("System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1");
private INamedTypeSymbol? EnumeratorCancellationAttributeSymbol { get; } = compilation.GetBestTypeByMetadataName("System.Runtime.CompilerServices.EnumeratorCancellationAttribute");
private INamedTypeSymbol? XunitTestContextSymbol { get; } = compilation.GetBestTypeByMetadataName("Xunit.TestContext");

private bool HasExplicitCancellationTokenArgument(IInvocationOperation operation)
{
Expand Down Expand Up @@ -179,7 +180,7 @@ public void AnalyzeInvocation(OperationAnalysisContext context)
if (parentMethod is not null && parentMethod.IsOverrideOrInterfaceImplementation())
return;

context.ReportDiagnostic(UseAnOverloadThatHasCancellationTokenRule, CreateProperties(availableCancellationTokens, parameterInfo), operation, string.Join(", ", availableCancellationTokens));
context.ReportDiagnostic(UseAnOverloadThatHasCancellationTokenRule, CreateProperties(availableCancellationTokens, parameterInfo), operation);
}
}

Expand Down Expand Up @@ -309,7 +310,9 @@ public void AnalyzeLoop(OperationAnalysisContext context)

private string[] FindCancellationTokens(IOperation operation, CancellationToken cancellationToken)
{

var availableSymbols = new List<NameAndType>();

foreach (var symbol in operation.LookupAvailableSymbols(cancellationToken))
{
var symbolType = symbol.GetSymbolType();
Expand All @@ -319,7 +322,7 @@ private string[] FindCancellationTokens(IOperation operation, CancellationToken
availableSymbols.Add(new(symbol.Name, symbolType));
}

if (availableSymbols.Count == 0)
if (availableSymbols.Count == 0 && XunitTestContextSymbol is null)
return [];

var isInStaticContext = operation.IsInStaticContext(cancellationToken);
Expand Down Expand Up @@ -348,6 +351,11 @@ private string[] FindCancellationTokens(IOperation operation, CancellationToken
}
}

if (XunitTestContextSymbol != null)
{
paths.Add("Xunit.TestContext.Current.CancellationToken");
}

if (paths.Count == 0)
return [];

Expand Down
7 changes: 7 additions & 0 deletions tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,16 @@ async Task<string[]> Download()
using var stream = await SharedHttpClient.Instance.GetStreamAsync(new Uri($"https://www.nuget.org/api/v2/package/{packageName}/{version}")).ConfigureAwait(false);
using var zip = new ZipArchive(stream, ZipArchiveMode.Read);

var hasEntry = false;
foreach (var entry in zip.Entries.Where(file => paths.Any(path => file.FullName.StartsWith(path, StringComparison.Ordinal))))
{
entry.ExtractToFile(Path.Combine(tempFolder, entry.Name), overwrite: true);
hasEntry = true;
}

if (!hasEntry)
{
throw new InvalidOperationException("The NuGet package " + packageName + "@" + version + " does not contain any file matching the paths " + string.Join(", ", paths));
}

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1228,4 +1228,47 @@ class Sample
.WithOutputKind(Microsoft.CodeAnalysis.OutputKind.ConsoleApplication)
.ValidateAsync();
}

[Fact]
public async Task Xunit2()
{
await CreateProjectBuilder()
.AddNuGetReference("xunit.abstractions", "2.0.3", "lib/netstandard2.0/")
.WithSourceCode("""
using System.Threading;
using System.Threading.Tasks;
{|MA0032:Sample.Repro()|};
class Sample
{
public static void Repro() => throw null;
public static void Repro(CancellationToken cancellationToken) => throw null;
}
""")
.WithOutputKind(Microsoft.CodeAnalysis.OutputKind.ConsoleApplication)
.ValidateAsync();
}

[Fact]
public async Task Xunit3()
{
await CreateProjectBuilder()
.AddNuGetReference("xunit.v3.extensibility.core", "1.0.0", "lib/netstandard2.0/")
.WithSourceCode("""
using System.Threading;
using System.Threading.Tasks;
{|MA0040:Sample.Repro()|};
class Sample
{
public static void Repro() => throw null;
public static void Repro(CancellationToken cancellationToken) => throw null;
}
""")
.WithOutputKind(Microsoft.CodeAnalysis.OutputKind.ConsoleApplication)
.ShouldReportDiagnosticWithMessage("Use an overload with a CancellationToken, available tokens: Xunit.TestContext.Current.CancellationToken")
.ValidateAsync();
}
}

0 comments on commit aa97561

Please sign in to comment.