FP on S8949: cancellation token is provided

Rule S8949 is about using cancellation tokens provided by method arguments when possible. If we take the following snippet:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;

public static class S8949
{
	/// <summary>Gets the diagnostics for the specified analyzers.</summary>
	[Pure]
	public static async Task<IReadOnlyCollection<Diagnostic>> GetDiagnosticsAsync(
		Compilation compilation,
		ImmutableArray<DiagnosticAnalyzer> analyzers,
		IEnumerable<AdditionalText> texts,
		CancellationToken cancellationToken = default)
	{
		var options = compilation.Options.WithSpecificDiagnosticOptions([]);
		var analyzerOptions = new AnalyzerOptions([.. texts]);

		var diagnostics = await compilation // FP, cancelation token is passed.
			.WithOptions(options) 
			.WithAnalyzers(analyzers, analyzerOptions)
			.GetAllDiagnosticsAsync(cancellationToken);

		return diagnostics;
	}
}

It reports:

Pass the ‘cancellationToken’ to this method to allow cancellation of the operation, or use ‘CancellationToken.None’ to opt out explicitly.

it fails to detect that cancellationToken is actually provided, hence the FP. It is worth noticing that neither.WithOptions() and .WithAnalyzers() have an overload that has a CancellationToken argument, and that all 3 methods in the chain are extension methods. I’m not sure if the last part is relevant, but it might be.

Reported by: SonarAnalyzer.CSharp v10.34.0.338

@lijun.chen Could you confirm this as an issue? I understand you’re busy, and that you can not give an ETA. It helps me to know that it could be confirmed and is somewhere on a backlog.

Hey @Corniel, I understand you’re a very active member of the Community and are familiar with some of the staff, but we discourage mentioning staff members (or users in general) directly. This post is flagged for the team to look into, they’ll find some time to process it eventually.

Hi @Corniel

Apologies for the delay, and thanks for reporting this problem. I agree this is a false positive.

Actually, WithAnalyzers does have an overload that accepts a CancellationToken, but Roslyn marks it obsolete and recommends using the overload without a token.

That being said, I see two improvements we could make to this rule:

  • It should exclude obsolete overloads when looking for alternatives that accept a CancellationToken. This would prevent this false positive.
  • It should point the issue more precisely at the offending method it is reporting. Here, the issue is raised for WithAnalyzers, but the issue location currently covers compilation.WithOptions(options).WithAnalyzers, making it confusing.

Hope this helps.

I have created an internal ticket for these improvements.

Best,

Lijun

Sorry for that. @lijun.chen Responded on my other FP, and my impulse to think, that they just mist this one was too big. I’ll try to behave better next time. :slight_smile:

I missed that. Reason is that Visual Studio doesn’t even show the obsolete option. Not in the tooltip, and not in the auto complete option. An extra reason not to advise it. :wink:

That’s [EditorBrowsable(EditorBrowsableState.Never)], which should probably an exclusion criterion in addition to [Obsolete].