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
Expand Up @@ -88,7 +88,10 @@ private static bool IsDefaultLike(IOperation operation, ITypeSymbol cancellation
|| operation.Syntax.IsKind(SyntaxKind.DefaultLiteralExpression))
return true;

return operation is IPropertyReferenceOperation { Property.Name: "None", Property.ContainingType: { } containingType }
return operation is IPropertyReferenceOperation
{
Property: { Name: "None", ContainingType: { } containingType }
}
&& containingType.IsEqualTo(cancellationTokenType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,9 @@ private static async Task<Document> ApplyAsync(
Diagnostic diagnostic,
CancellationToken cancellationToken)
{
if (!diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterName, out var parameterName))
return document;
if (string.IsNullOrWhiteSpace(parameterName))
return document;

if (!diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterIndex, out var parameterIndexText)
if (!diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterName, out var parameterName)
|| string.IsNullOrWhiteSpace(parameterName)
|| !diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterIndex, out var parameterIndexText)
|| !int.TryParse(parameterIndexText, out var parameterIndex))
return document;
Comment on lines +51 to 55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Don't block the fix when ParameterName is missing.

ApplyAsync already has a positional fallback, so requiring ParameterName up front turns a recoverable diagnostic into a no-op. Keep ParameterIndex as the hard requirement and treat ParameterName as optional for the named-argument branch.

♻️ Proposed fix
-        if (!diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterName, out var parameterName)
-            || string.IsNullOrWhiteSpace(parameterName)
-            || !diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterIndex, out var parameterIndexText)
-            || !int.TryParse(parameterIndexText, out var parameterIndex))
+        if (!diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterIndex, out var parameterIndexText)
+            || !int.TryParse(parameterIndexText, out var parameterIndex))
             return document;
+
+        diagnostic.Properties.TryGetValue(DiagnosticPropertyNames.ParameterName, out var parameterName);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/ANcpLua.Roslyn.Utilities.Examples.XunitCancellationCodeFixes/MissingCancellationTokenFixer.cs`
around lines 51 - 55, The current guard in MissingCancellationTokenFixer
prevents the code fix from running if DiagnosticPropertyNames.ParameterName is
absent; change the logic so that ApplyAsync only treats
DiagnosticPropertyNames.ParameterIndex as mandatory (keep the TryGetValue +
int.TryParse for parameterIndex and return document if that fails) while making
ParameterName optional: attempt to read DiagnosticPropertyNames.ParameterName
into parameterName if present but do not bail if it's missing or whitespace,
letting ApplyAsync use its positional fallback when parameterName is null/empty.
Update the conditional that now checks both properties to only require
parameterIndex and proceed otherwise.


Expand Down
4 changes: 2 additions & 2 deletions src/ANcpLua.Roslyn.Utilities.Testing/GeneratorTestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public GeneratorTestEngine WithStepTracking(bool trackSteps = true)
/// <returns>A task that resolves to a <see cref="CSharpCompilation" />.</returns>
public async Task<CSharpCompilation> CreateCompilationAsync(CancellationToken cancellationToken = default)
{
var resolvedReferences = await _referenceAssemblies.ResolveAsync(LanguageNames.CSharp, cancellationToken);
var resolvedReferences = await _referenceAssemblies.ResolveAsync(LanguageNames.CSharp, cancellationToken).ConfigureAwait(false);

var allReferences = resolvedReferences
.Concat(_references)
Expand Down Expand Up @@ -163,7 +163,7 @@ public GeneratorDriver CreateDriver()
internal async Task<(GeneratorDriverRunResult FirstRun, GeneratorDriverRunResult SecondRun)> RunTwiceAsync(
CancellationToken cancellationToken = default)
{
var compilation = await CreateCompilationAsync(cancellationToken);
var compilation = await CreateCompilationAsync(cancellationToken).ConfigureAwait(false);
var driver = CreateDriver();

// First run
Expand Down
8 changes: 4 additions & 4 deletions src/ANcpLua.Roslyn.Utilities.Testing/LogAssert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ public static async Task ShouldEventuallyContain(
collector,
logs => logs.Any(r => r.Message.Contains(text)),
timeout,
ct);
ct).ConfigureAwait(false);

Assert.True(found,
$"Timed out waiting for log containing '{text}'.\nActual logs:\n{collector.FormatLogs()}");
Expand All @@ -355,7 +355,7 @@ public static async Task ShouldEventuallyHaveCount(
collector,
logs => logs.Count >= count,
timeout,
ct);
ct).ConfigureAwait(false);

Assert.True(found,
$"Timed out waiting for {count} logs, got {collector.GetSnapshot().Count}.\nActual logs:\n{collector.FormatLogs()}");
Expand All @@ -379,7 +379,7 @@ public static async Task ShouldEventuallyHaveLevel(
collector,
logs => logs.Any(r => r.Level == level),
timeout,
ct);
ct).ConfigureAwait(false);

Assert.True(found,
$"Timed out waiting for {level} log.\nActual logs:\n{collector.FormatLogs()}");
Expand All @@ -401,7 +401,7 @@ public static async Task ShouldEventuallySatisfy(
TimeSpan? timeout = null,
CancellationToken ct = default)
{
var found = await WaitForCondition(collector, condition, timeout, ct);
var found = await WaitForCondition(collector, condition, timeout, ct).ConfigureAwait(false);

Assert.True(found,
because ?? $"Timed out waiting for condition.\nActual logs:\n{collector.FormatLogs()}");
Expand Down
14 changes: 7 additions & 7 deletions src/ANcpLua.Roslyn.Utilities.Testing/MSBuild/DotNetSdkHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public static async Task<FullPath> Get(NetSdkVersion version)
if (Values.TryGetValue(version, out var result))
return result;

using (await KeyedAsyncLock.LockAsync(version))
using (await KeyedAsyncLock.LockAsync(version).ConfigureAwait(false))
{
if (Values.TryGetValue(version, out result))
return result;
Expand All @@ -114,9 +114,9 @@ public static async Task<FullPath> Get(NetSdkVersion version)
_ => throw new NotSupportedException($"SDK version {version} is not supported")
};

var products = await ProductCollection.GetAsync();
var products = await ProductCollection.GetAsync().ConfigureAwait(false);
var product = products.Single(a => a.ProductName == ".NET" && a.ProductVersion == versionString);
var releases = await product.GetReleasesAsync();
var releases = await product.GetReleasesAsync().ConfigureAwait(false);
var latestRelease = releases.Single(r => r.Version == product.LatestReleaseVersion);
var latestSdk = latestRelease.Sdks.MaxBy(static sdk => sdk.Version)
?? throw new InvalidOperationException($"No SDK found for .NET {versionString}");
Expand All @@ -135,19 +135,19 @@ public static async Task<FullPath> Get(NetSdkVersion version)

var tempFolder = FullPath.GetTempPath() / "dotnet" / Guid.NewGuid().ToString("N");

var bytes = await HttpClient.GetByteArrayAsync(file.Address);
var bytes = await HttpClient.GetByteArrayAsync(file.Address).ConfigureAwait(false);
if (Path.GetExtension(file.Name) is ".zip")
{
using var ms = new MemoryStream(bytes);
var zip = new ZipArchive(ms);
await zip.ExtractToDirectoryAsync(tempFolder, true);
await zip.ExtractToDirectoryAsync(tempFolder, true).ConfigureAwait(false);
}
else
{
using var ms = new MemoryStream(bytes);
await using var gz = new GZipStream(ms, CompressionMode.Decompress);
await using var tar = new TarReader(gz);
while (await tar.GetNextEntryAsync() is { } entry)
while ((await tar.GetNextEntryAsync().ConfigureAwait(false)) is { } entry)
{
var destinationPath = tempFolder / entry.Name;
switch (entry.EntryType)
Expand All @@ -161,7 +161,7 @@ public static async Task<FullPath> Get(NetSdkVersion version)
Directory.CreateDirectory(parentDir);
var entryStream = entry.DataStream;
await using var outputStream = File.Create(destinationPath);
if (entryStream is not null) await entryStream.CopyToAsync(outputStream);
if (entryStream is not null) await entryStream.CopyToAsync(outputStream).ConfigureAwait(false);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ public async ValueTask InitializeAsync()
}

// Local development mode: pre-warm the cache
await PreWarmNuGetCacheAsync();
await PreWarmNuGetCacheAsync().ConfigureAwait(false);
}

/// <summary>
/// Disposes the fixture and cleans up the temporary package directory.
/// </summary>
public virtual async ValueTask DisposeAsync()
{
await _packageDirectory.DisposeAsync();
await _packageDirectory.DisposeAsync().ConfigureAwait(false);
GC.SuppressFinalize(this);
}

Expand Down Expand Up @@ -218,7 +218,7 @@ private async Task PreWarmNuGetCacheAsync()
</packageSources>
</configuration>
""";
await File.WriteAllTextAsync(warmupDir / "NuGet.config", nugetConfig);
await File.WriteAllTextAsync(warmupDir / "NuGet.config", nugetConfig).ConfigureAwait(false);

var packageRefs = string.Join("\n ",
_preWarmPackages.Select(static p =>
Expand All @@ -234,7 +234,7 @@ private async Task PreWarmNuGetCacheAsync()
</ItemGroup>
</Project>
""";
await File.WriteAllTextAsync(warmupDir / "warmup.csproj", csproj);
await File.WriteAllTextAsync(warmupDir / "warmup.csproj", csproj).ConfigureAwait(false);

var psi = new ProcessStartInfo("dotnet")
{
Expand All @@ -246,7 +246,7 @@ private async Task PreWarmNuGetCacheAsync()
};
psi.ArgumentList.AddRange("restore", "--no-cache");

var result = await psi.RunAsTaskAsync(CancellationToken.None);
var result = await psi.RunAsTaskAsync(CancellationToken.None).ConfigureAwait(false);
if (result.ExitCode is not 0)
throw new InvalidOperationException(
$"NuGet cache pre-warm failed with exit code {result.ExitCode}. Output: {result.Output}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
{
BuildCount++;

var psi = new ProcessStartInfo(await DotNetSdkHelpers.Get(SdkVersion))
var psi = new ProcessStartInfo(await DotNetSdkHelpers.Get(SdkVersion).ConfigureAwait(false))
{
WorkingDirectory = Directory.FullPath,
RedirectStandardOutput = true,
Expand Down Expand Up @@ -310,7 +310,7 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
foreach (var env in environmentVariables)
psi.Environment[env.Name] = env.Value;

var result = await psi.RunAsTaskAsync();
var result = await psi.RunAsTaskAsync().ConfigureAwait(false);

// Retry logic for SDK resolution failures
const int maxRetries = 5;
Expand All @@ -320,8 +320,8 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
line.Text.Contains("The project file may be invalid or missing targets required for restore",
StringComparison.Ordinal)))
{
await Task.Delay(100 * (1 << retry));
result = await psi.RunAsTaskAsync();
await Task.Delay(100 * (1 << retry)).ConfigureAwait(false);
result = await psi.RunAsTaskAsync().ConfigureAwait(false);
}
else
{
Expand All @@ -332,11 +332,11 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
SarifFile? sarif = null;
if (File.Exists(sarifPath))
{
var bytes = await File.ReadAllBytesAsync(sarifPath);
var bytes = await File.ReadAllBytesAsync(sarifPath).ConfigureAwait(false);
sarif = JsonSerializer.Deserialize<SarifFile>(bytes);
}

var binlogContent = await File.ReadAllBytesAsync(Directory.FullPath / "msbuild.binlog");
var binlogContent = await File.ReadAllBytesAsync(Directory.FullPath / "msbuild.binlog").ConfigureAwait(false);

return new BuildResult(result.ExitCode, result.Output, sarif, binlogContent);
}
Expand Down Expand Up @@ -564,10 +564,10 @@ public void AddDirectoryBuildPropsFile(string postSdkContent, string preSdkConte
/// </remarks>
public async Task InitializeGitRepoAsync()
{
await ExecuteGitCommand("init");
await ExecuteGitCommand("add", ".");
await ExecuteGitCommand("commit", "-m", "Initial commit");
await ExecuteGitCommand("remote", "add", "origin", "https://github.com/ancplua/sample.git");
await ExecuteGitCommand("init").ConfigureAwait(false);
await ExecuteGitCommand("add", ".").ConfigureAwait(false);
await ExecuteGitCommand("commit", "-m", "Initial commit").ConfigureAwait(false);
await ExecuteGitCommand("remote", "add", "origin", "https://github.com/ancplua/sample.git").ConfigureAwait(false);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ protected override async Task<BuildResult> QuickBuild(
.WithOutputType(Val.Library)
.WithProperties(extraProps)
.AddSource("Code.cs", code)
.BuildAsync();
.BuildAsync().ConfigureAwait(false);
}

/// <summary>
Expand Down Expand Up @@ -352,6 +352,6 @@ protected override async Task<BuildResult> BuildExe(
.WithOutputType(Val.Exe)
.WithProperties(extraProps)
.AddSource("Program.cs", code)
.BuildAsync();
.BuildAsync().ConfigureAwait(false);
}
}
16 changes: 8 additions & 8 deletions src/ANcpLua.Roslyn.Utilities.Testing/MSBuild/ProjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ public ProjectBuilder(ITestOutputHelper? testOutputHelper = null)
/// </remarks>
public virtual async ValueTask DisposeAsync()
{
await Directory.DisposeAsync();
await Directory.DisposeAsync().ConfigureAwait(false);
GC.SuppressFinalize(this);
}

Expand Down Expand Up @@ -1055,14 +1055,14 @@ public virtual async Task<BuildResult> ExecuteDotnetCommandAsync(string command,
foreach (var file in System.IO.Directory.GetFiles(Directory.FullPath, "*", SearchOption.AllDirectories))
{
TestOutputHelper.WriteLine("File: " + file);
var content = await File.ReadAllTextAsync(file);
var content = await File.ReadAllTextAsync(file).ConfigureAwait(false);
TestOutputHelper.WriteLine(content);
}

TestOutputHelper.WriteLine("-------- dotnet " + command);
}

var psi = new ProcessStartInfo(await DotNetSdkHelpers.Get(SdkVersion))
var psi = new ProcessStartInfo(await DotNetSdkHelpers.Get(SdkVersion).ConfigureAwait(false))
{
WorkingDirectory = Directory.FullPath,
RedirectStandardOutput = true,
Expand Down Expand Up @@ -1096,13 +1096,13 @@ public virtual async Task<BuildResult> ExecuteDotnetCommandAsync(string command,

TestOutputHelper?.WriteLine("Executing: " + psi.FileName + " " + string.Join(' ', psi.ArgumentList));

var result = await psi.RunAsTaskAsync();
var result = await psi.RunAsTaskAsync().ConfigureAwait(false);

TestOutputHelper?.WriteLine("Process exit code: " + result.ExitCode);
TestOutputHelper?.WriteLine(result.Output.ToString());

var sarif = await LoadSarifAsync(Directory.FullPath);
var binlogContent = await File.ReadAllBytesAsync(Directory.FullPath / "msbuild.binlog");
var sarif = await LoadSarifAsync(Directory.FullPath).ConfigureAwait(false);
var binlogContent = await File.ReadAllBytesAsync(Directory.FullPath / "msbuild.binlog").ConfigureAwait(false);
var recordedProperties = LoadRecordedProperties(Directory.FullPath);

return new BuildResult(result.ExitCode, result.Output, sarif, binlogContent)
Expand Down Expand Up @@ -1143,14 +1143,14 @@ public virtual async Task<BuildResult> ExecuteDotnetCommandAsync(string command,

if (sarifFiles.Count == 1)
{
var bytes = await File.ReadAllBytesAsync(sarifFiles[0]);
var bytes = await File.ReadAllBytesAsync(sarifFiles[0]).ConfigureAwait(false);
return JsonSerializer.Deserialize<SarifFile>(bytes);
}

var allRuns = new List<SarifFileRun>();
foreach (var path in sarifFiles)
{
var bytes = await File.ReadAllBytesAsync(path);
var bytes = await File.ReadAllBytesAsync(path).ConfigureAwait(false);
var sarif = JsonSerializer.Deserialize<SarifFile>(bytes);
if (sarif?.Runs is not null)
allRuns.AddRange(sarif.Runs);
Expand Down
Loading