예제 #1
0
        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);
            });
        }
예제 #3
0
        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);
            }
        }