public override void Initialize(AnalysisContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } base.Initialize(context); context.RegisterCompilationStartAction(startContext => { INamedTypeSymbol taskType = startContext.Compilation.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task); INamedTypeSymbol valueTaskType = startContext.Compilation.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_ValueTask_T); var windowsRuntimeTypes = default(WindowsRuntimeAsyncTypes); INamedTypeSymbol asyncAction = startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncAction"); if (asyncAction != null) { windowsRuntimeTypes = new WindowsRuntimeAsyncTypes( asyncAction: asyncAction, asyncActionWithProgress: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncActionWithProgress`1"), asyncOperation: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncOperation`1"), asyncOperationWithProgress: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncOperationWithProgress`2")); } startContext.RegisterSyntaxNodeAction(nodeContext => AnalyzeMethodDeclaration(nodeContext, taskType, valueTaskType, windowsRuntimeTypes), SyntaxKind.MethodDeclaration); }); }
public override void Initialize(AnalysisContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } base.Initialize(context); context.RegisterCompilationStartAction(startContext => { if (startContext.IsAnalyzerSuppressed(DiagnosticDescriptors.NonAsynchronousMethodNameShouldNotEndWithAsync)) { return; } INamedTypeSymbol taskType = startContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task"); INamedTypeSymbol valueTaskType = startContext.Compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1"); var windowsRuntimeTypes = default(WindowsRuntimeAsyncTypes); INamedTypeSymbol asyncAction = startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncAction"); if (asyncAction != null) { windowsRuntimeTypes = new WindowsRuntimeAsyncTypes( asyncAction: asyncAction, asyncActionWithProgress: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncActionWithProgress`1"), asyncOperation: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncOperation`1"), asyncOperationWithProgress: startContext.Compilation.GetTypeByMetadataName("Windows.Foundation.IAsyncOperationWithProgress`2")); } startContext.RegisterSyntaxNodeAction(nodeContext => AnalyzeMethodDeclaration(nodeContext, taskType, valueTaskType, windowsRuntimeTypes), SyntaxKind.MethodDeclaration); }); }
public static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context, INamedTypeSymbol taskType, INamedTypeSymbol valueTaskType, WindowsRuntimeAsyncTypes windowsRuntimeAsyncTypes) { var methodDeclaration = (MethodDeclarationSyntax)context.Node; if (!methodDeclaration.Identifier.ValueText.EndsWith(AsyncSuffix, StringComparison.Ordinal)) { return; } IMethodSymbol methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); if (methodSymbol == null) { return; } if (methodSymbol.IsAsync) { return; } if (!methodSymbol.Name.EndsWith(AsyncSuffix, StringComparison.Ordinal)) { return; } ITypeSymbol typeSymbol = methodSymbol.ReturnType; if (CanHaveAsyncSuffix()) { return; } SyntaxToken identifier = methodDeclaration.Identifier; context.ReportDiagnostic( DiagnosticDescriptors.NonAsynchronousMethodNameShouldNotEndWithAsync, identifier); context.ReportDiagnostic( DiagnosticDescriptors.NonAsynchronousMethodNameShouldNotEndWithAsyncFadeOut, Location.Create(identifier.SyntaxTree, TextSpan.FromBounds(identifier.Span.End - AsyncSuffix.Length, identifier.Span.End))); bool CanHaveAsyncSuffix() { if (typeSymbol.IsTupleType) { return(false); } if (typeSymbol.SpecialType != SpecialType.None) { return(false); } if (!typeSymbol.IsTypeKind(TypeKind.Class, TypeKind.Struct, TypeKind.Interface)) { return(false); } if (!(typeSymbol is INamedTypeSymbol namedTypeSymbol)) { return(false); } INamedTypeSymbol constructedFrom = namedTypeSymbol.ConstructedFrom; if (constructedFrom.Equals(valueTaskType)) { return(true); } if (namedTypeSymbol.EqualsOrInheritsFrom(taskType)) { return(true); } INamedTypeSymbol asyncAction = windowsRuntimeAsyncTypes.IAsyncAction; if (asyncAction != null) { if (namedTypeSymbol.Equals(asyncAction)) { return(false); } if (namedTypeSymbol.Implements(asyncAction, allInterfaces: true)) { return(true); } if (namedTypeSymbol.Arity > 0 && namedTypeSymbol.TypeKind == TypeKind.Interface) { if (constructedFrom.Equals(windowsRuntimeAsyncTypes.IAsyncActionWithProgress)) { return(true); } if (constructedFrom.Equals(windowsRuntimeAsyncTypes.IAsyncOperation)) { return(true); } if (constructedFrom.Equals(windowsRuntimeAsyncTypes.IAsyncOperationWithProgress)) { return(true); } } } return(false); } }