예제 #1
0
    public static bool IsApiControllerAction(ApiControllerSymbolCache symbolCache, IMethodSymbol method)
    {
        if (method == null)
        {
            return(false);
        }

        if (method.ReturnsVoid || method.ReturnType.TypeKind == TypeKind.Error)
        {
            return(false);
        }

        if (!MvcFacts.IsController(method.ContainingType, symbolCache.ControllerAttribute, symbolCache.NonControllerAttribute))
        {
            return(false);
        }

        if (!method.ContainingType.HasAttribute(symbolCache.IApiBehaviorMetadata, inherit: true) &&
            !method.ContainingAssembly.HasAttribute(symbolCache.IApiBehaviorMetadata))
        {
            return(false);
        }

        if (!MvcFacts.IsControllerAction(method, symbolCache.NonActionAttribute, symbolCache.IDisposableDispose))
        {
            return(false);
        }

        return(true);
    }
예제 #2
0
        private void IsControllerReturnsTrue(Type type)
        {
            var compilation = GetIsControllerCompilation();
            var typeSymbol  = compilation.GetTypeByMetadataName(type.FullName);

            // Act
            var isController = MvcFacts.IsController(typeSymbol);

            // Assert
            Assert.True(isController);
        }
예제 #3
0
        private void IsActionReturnsTrue(Type type, string methodName)
        {
            var compilation       = GetIsControllerActionCompilation();
            var disposableDispose = GetDisposableDispose(compilation);
            var typeSymbol        = compilation.GetTypeByMetadataName(type.FullName);
            var method            = (IMethodSymbol)typeSymbol.GetMembers(methodName).First();

            // Act
            var isControllerAction = MvcFacts.IsControllerAction(method, disposableDispose);

            // Assert
            Assert.True(isControllerAction);
        }
예제 #4
0
        public void IsAction_ReturnsTrueForNotDisposableDisposeOnTypeWithImplicitImplementation()
        {
            var compilation       = GetIsControllerActionCompilation();
            var disposableDispose = GetDisposableDispose(compilation);
            var typeSymbol        = compilation.GetTypeByMetadataName(typeof(NotDisposableWithDisposeThatIsNotInterfaceContract).FullName);
            var method            = typeSymbol.GetMembers(nameof(IDisposable.Dispose)).OfType <IMethodSymbol>().First(f => !f.ReturnsVoid);

            // Act
            var isControllerAction = MvcFacts.IsControllerAction(method, disposableDispose);

            // Assert
            Assert.True(isControllerAction);
        }
예제 #5
0
    private async Task IsControllerReturnsTrue(Type type)
    {
        var compilation = await GetIsControllerCompilation();

        var controllerAttribute    = compilation.GetTypeByMetadataName(ControllerAttribute);
        var nonControllerAttribute = compilation.GetTypeByMetadataName(NonControllerAttribute);
        var typeSymbol             = compilation.GetTypeByMetadataName(type.FullName);

        // Act
        var isController = MvcFacts.IsController(typeSymbol, controllerAttribute, nonControllerAttribute);

        // Assert
        Assert.True(isController);
    }
예제 #6
0
    private async Task IsActionReturnsFalse(Type type, string methodName)
    {
        var compilation = await GetIsControllerActionCompilation();

        var nonActionAttribute = compilation.GetTypeByMetadataName(NonActionAttribute);
        var disposableDispose  = GetDisposableDispose(compilation);
        var typeSymbol         = compilation.GetTypeByMetadataName(type.FullName);
        var method             = (IMethodSymbol)typeSymbol.GetMembers(methodName).First();

        // Act
        var isControllerAction = MvcFacts.IsControllerAction(method, nonActionAttribute, disposableDispose);

        // Assert
        Assert.False(isControllerAction);
    }
예제 #7
0
        private void CanBeControllerReturnsTrue(Type type)
        {
            var compilation = GetIsControllerCompilation();
            var syntaxTree  = compilation.GetTypeByMetadataName(type.FullName).DeclaringSyntaxReferences.Single().SyntaxTree;

            var typeName = type.IsGenericType ? type.Name.Substring(0, type.Name.IndexOf('`')) : type.Name;
            var typeDeclarationSyntax = syntaxTree.GetRoot().DescendantNodes()
                                        .OfType <TypeDeclarationSyntax>()
                                        .First(node => node.Identifier.ToString() == typeName);

            // Act
            var canBeController = MvcFacts.CanBeController(typeDeclarationSyntax);

            // Assert
            Assert.True(canBeController);
        }
예제 #8
0
    private static void InitializeWorker(CompilationStartAnalysisContext compilationStartAnalysisContext, SymbolCache symbolCache)
    {
        compilationStartAnalysisContext.RegisterSymbolAction(symbolAnalysisContext =>
        {
            var method = (IMethodSymbol)symbolAnalysisContext.Symbol;
            if (method.MethodKind != MethodKind.Ordinary)
            {
                return;
            }

            if (method.Parameters.Length == 0)
            {
                return;
            }

            if (!MvcFacts.IsController(method.ContainingType, symbolCache.ControllerAttribute, symbolCache.NonControllerAttribute) ||
                !MvcFacts.IsControllerAction(method, symbolCache.NonActionAttribute, symbolCache.IDisposableDispose))
            {
                return;
            }

            if (method.ContainingType.HasAttribute(symbolCache.IApiBehaviorMetadata, inherit: true))
            {
                // The issue of parameter name collision with properties affects complex model-bound types
                // and not input formatting. Ignore ApiController instances since they default to formatting.
                return;
            }

            for (var i = 0; i < method.Parameters.Length; i++)
            {
                var parameter = method.Parameters[i];
                if (IsProblematicParameter(symbolCache, parameter))
                {
                    var location = parameter.Locations.Length != 0 ?
                                   parameter.Locations[0] :
                                   Location.None;

                    symbolAnalysisContext.ReportDiagnostic(
                        Diagnostic.Create(
                            DiagnosticDescriptors.MVC1004_ParameterNameCollidesWithTopLevelProperty,
                            location,
                            parameter.Type.Name,
                            parameter.Name));
                }
            }
        }, SymbolKind.Method);
    }