-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Misc improvements #270
base: master
Are you sure you want to change the base?
Misc improvements #270
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,11 +33,10 @@ protected DiagnosticAnalyzerBase(params DiagnosticDescriptor[] diagnostics) | |
public sealed override void Initialize(AnalysisContext context) | ||
{ | ||
context.EnableConcurrentExecution(); | ||
|
||
if (ReportDiagnosticsOnGeneratedCode) | ||
{ | ||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); | ||
} | ||
Comment on lines
-37
to
-40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Analyze | ReportDiagnostics is already the default. So, currently |
||
|
||
var flags = ReportDiagnosticsOnGeneratedCode ? GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics : GeneratedCodeAnalysisFlags.None; | ||
|
||
context.ConfigureGeneratedCodeAnalysis(flags); | ||
|
||
InitializeCore(context); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
using System.Runtime.CompilerServices; | ||
using System.Collections.Immutable; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading.Tasks; | ||
using ErrorProne.NET.CoreAnalyzers; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.CodeAnalysis.Operations; | ||
using CompilationExtensions = ErrorProne.NET.Core.CompilationExtensions; | ||
|
||
namespace ErrorProne.NET.AsyncAnalyzers | ||
{ | ||
|
@@ -27,38 +26,56 @@ public ConfigureAwaitRequiredAnalyzer() | |
/// <inheritdoc /> | ||
protected override void InitializeCore(AnalysisContext context) | ||
{ | ||
context.RegisterSyntaxNodeAction(AnalyzeAwaitExpression, SyntaxKind.AwaitExpression); | ||
context.RegisterCompilationStartAction(context => | ||
{ | ||
var compilation = context.Compilation; | ||
|
||
var configureAwaitConfig = ConfigureAwaitConfiguration.TryGetConfigureAwait(context.Compilation); | ||
if (configureAwaitConfig != ConfigureAwait.UseConfigureAwaitFalse) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All callbacks are checking for this. So, we can actually check it once in compilation start, and not register any action at all when not needed. |
||
{ | ||
return; | ||
} | ||
|
||
var taskType = compilation.GetTypeByMetadataName(typeof(Task).FullName); | ||
if (taskType is null) | ||
{ | ||
return; | ||
} | ||
|
||
var configureAwaitMethods = taskType.GetMembers("ConfigureAwait").OfType<IMethodSymbol>().ToImmutableArray(); | ||
if (configureAwaitMethods.IsEmpty) | ||
{ | ||
return; | ||
} | ||
|
||
var yieldAwaitable = compilation.GetTypeByMetadataName(typeof(YieldAwaitable).FullName); | ||
|
||
context.RegisterOperationAction(context => AnalyzeAwaitOperation(context, configureAwaitMethods, yieldAwaitable), OperationKind.Await); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switched from syntax to operation. At the end, |
||
}); | ||
|
||
} | ||
|
||
private void AnalyzeAwaitExpression(SyntaxNodeAnalysisContext context) | ||
private static void AnalyzeAwaitOperation(OperationAnalysisContext context, ImmutableArray<IMethodSymbol> configureAwaitMethods, INamedTypeSymbol? yieldAwaitable) | ||
{ | ||
var invocation = (AwaitExpressionSyntax)context.Node; | ||
var awaitOperation = (IAwaitOperation)context.Operation; | ||
|
||
var configureAwaitConfig = ConfigureAwaitConfiguration.TryGetConfigureAwait(context.Compilation); | ||
if (configureAwaitConfig == ConfigureAwait.UseConfigureAwaitFalse) | ||
if (awaitOperation.Operation is IInvocationOperation configureAwaitOperation) | ||
{ | ||
var operation = context.SemanticModel.GetOperation(invocation, context.CancellationToken); | ||
if (operation is IAwaitOperation awaitOperation) | ||
if (configureAwaitMethods.Contains(configureAwaitOperation.TargetMethod)) | ||
{ | ||
if (awaitOperation.Operation is IInvocationOperation configureAwaitOperation) | ||
{ | ||
if (configureAwaitOperation.TargetMethod.IsConfigureAwait(context.Compilation)) | ||
{ | ||
return; | ||
} | ||
|
||
if (CompilationExtensions.IsClrType(configureAwaitOperation.Type, context.Compilation, typeof(YieldAwaitable))) | ||
{ | ||
return; | ||
} | ||
} | ||
|
||
var location = awaitOperation.Syntax.GetLocation(); | ||
return; | ||
} | ||
|
||
var diagnostic = Diagnostic.Create(Rule, location); | ||
context.ReportDiagnostic(diagnostic); | ||
if (SymbolEqualityComparer.Default.Equals(configureAwaitOperation.Type, yieldAwaitable)) | ||
{ | ||
return; | ||
} | ||
} | ||
|
||
var location = awaitOperation.Syntax.GetLocation(); | ||
|
||
var diagnostic = Diagnostic.Create(Rule, location); | ||
context.ReportDiagnostic(diagnostic); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code path was repeatedly called, and
GetTaskTypes
would callcompilation.GetTypeByMetadataName
. For performance, it's recommended to do this call once, in compilation start (i.e, usingRegisterCompilationStartAction
).So, instead of passing
Compilation
here, the symbols calculated in compilation start should be passed. Then, I needed to "group" all task symbols inTaskTypesInfo
instead of passing multiple parameters here.