/// <summary>
 /// Checks rule: Ensure that {0} is declared as public and sealed.
 /// </summary>
 private static void CheckDisposeSignatureRule(IMethodSymbol method, INamedTypeSymbol type, SymbolAnalysisContext context)
 {
     if (!method.IsPublic() ||
         method.IsAbstract || method.IsVirtual || (method.IsOverride && !method.IsSealed))
     {
         context.ReportDiagnostic(method.CreateDiagnostic(DisposeSignatureRule, $"{type.Name}.{method.Name}"));
     }
 }
 private static bool IsImplicitCastOperator(IMethodSymbol method, Compilation compilation)
 {
     if (!method.IsStatic || !method.IsPublic())
     {
         return(false);
     }
     return(method.Name == WellKnownMemberNames.ImplicitConversionName);
 }
        public static bool CanRefactor(
            InvocationExpressionSyntax invocation,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (invocation.ArgumentList?.Arguments.Any() == false)
            {
                ExpressionSyntax expression = invocation.Expression;

                if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)expression;

                    if (memberAccess.Name?.Identifier.ValueText.Equals("ToString", StringComparison.Ordinal) == true)
                    {
                        IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocation, cancellationToken);

                        if (methodSymbol.Name?.Equals("ToString", StringComparison.Ordinal) == true &&
                            !methodSymbol.IsGenericMethod &&
                            !methodSymbol.IsExtensionMethod &&
                            methodSymbol.IsPublic() &&
                            !methodSymbol.IsStatic &&
                            !methodSymbol.Parameters.Any() &&
                            methodSymbol.ReturnType?.IsString() == true)
                        {
                            if (methodSymbol.ContainingType?.IsString() == true)
                            {
                                return(true);
                            }
                            else if (invocation.IsParentKind(SyntaxKind.Interpolation))
                            {
                                if (methodSymbol.ContainingType?.IsObject() == true)
                                {
                                    return(true);
                                }
                                else if (methodSymbol.IsOverride)
                                {
                                    IMethodSymbol overridenMethod = methodSymbol.OverriddenMethod;

                                    while (overridenMethod != null)
                                    {
                                        if (overridenMethod.ContainingType?.IsObject() == true)
                                        {
                                            return(true);
                                        }

                                        overridenMethod = overridenMethod.OverriddenMethod;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Example #4
0
        private static bool IsEqualityOperator(IMethodSymbol method, Compilation compilation)
        {
            if (!method.IsStatic || !method.IsPublic())
            {
                return(false);
            }

            return(method.Name switch
            {
                WellKnownMemberNames.EqualityOperatorName
                or WellKnownMemberNames.InequalityOperatorName => true,
                _ => false,
            });
Example #5
0
        public static MethodSpecifier MethodSpecifierFromSymbol(IMethodSymbol method)
        {
            MethodModifiers modifiers = MethodModifiers.Private;

            if (method.IsPublic())
            {
                modifiers |= MethodModifiers.Public;
            }

            if (method.IsVirtual)
            {
                modifiers |= MethodModifiers.Virtual;
            }

            if (method.IsSealed)
            {
                modifiers |= MethodModifiers.Sealed;
            }

            if (method.IsAbstract)
            {
                modifiers |= MethodModifiers.Abstract;
            }

            if (method.IsStatic)
            {
                modifiers |= MethodModifiers.Static;
            }

            // TODO: Protected / Internal

            BaseType[] returnTypes = method.ReturnsVoid ?
                new BaseType[] { } :
                new BaseType[] { BaseTypeSpecifierFromSymbol(method.ReturnType) };

            Named<BaseType>[] parameterTypes = method.Parameters.Select(
                p => NamedBaseTypeSpecifierFromSymbol(p)).ToArray();

            BaseType[] genericArgs = method.TypeParameters.Select(
                p => BaseTypeSpecifierFromSymbol(p)).ToArray();

            return new MethodSpecifier(
                method.Name,
                parameterTypes,
                returnTypes,
                modifiers,
                TypeSpecifierFromSymbol(method.ContainingType),
                genericArgs);
        }
        private static bool IsEqualityOperator(IMethodSymbol method, Compilation compilation)
        {
            if (!method.IsStatic || !method.IsPublic())
            {
                return(false);
            }
            switch (method.Name)
            {
            case WellKnownMemberNames.EqualityOperatorName:
            case WellKnownMemberNames.InequalityOperatorName:
                return(true);

            default:
                return(false);
            }
        }
        public static bool CanRefactor(
            InvocationExpressionSyntax invocation,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (ParentIsElementAccessOrForEachExpression(invocation) &&
                invocation.ArgumentList?.Arguments.Any() == false)
            {
                ExpressionSyntax expression = invocation.Expression;

                if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)expression;

                    if (memberAccess.Name?.Identifier.ValueText.Equals("ToCharArray", StringComparison.Ordinal) == true)
                    {
                        IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocation, cancellationToken);

                        if (string.Equals(methodSymbol.Name, "ToCharArray", StringComparison.Ordinal) &&
                            !methodSymbol.IsGenericMethod &&
                            !methodSymbol.IsExtensionMethod &&
                            methodSymbol.IsPublic() &&
                            !methodSymbol.IsStatic &&
                            !methodSymbol.Parameters.Any() &&
                            methodSymbol.ContainingType?.IsString() == true)
                        {
                            ITypeSymbol returnType = methodSymbol.ReturnType;

                            if (returnType?.IsArrayType() == true)
                            {
                                var arrayType = (IArrayTypeSymbol)returnType;

                                if (arrayType.ElementType?.IsChar() == true)
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Example #8
0
        private string GetInternalMethodMetaInfo(IMethodSymbol symbol, MethodMetaType metaType)
        {
            Contract.Assert(symbol != null);
            if (!symbol.IsPublic())
            {
                return(null);
            }

            string metaInfo = null;

            if (symbol.IsFromAssembly())
            {
                metaInfo = GetTypeMetaInfo(symbol)?.GetMethodMetaInfo(symbol.Name)?.GetMetaInfo(symbol, metaType);
            }

            if (metaInfo == null)
            {
                if (symbol.IsOverride)
                {
                    if (symbol.OverriddenMethod != null)
                    {
                        metaInfo = GetInternalMethodMetaInfo(symbol.OverriddenMethod, metaType);
                    }
                }
                else
                {
                    var interfaceImplementations = symbol.InterfaceImplementations();
                    if (interfaceImplementations != null)
                    {
                        foreach (IMethodSymbol interfaceMethod in interfaceImplementations)
                        {
                            metaInfo = GetInternalMethodMetaInfo(interfaceMethod, metaType);
                            if (metaInfo != null)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            return(metaInfo);
        }
Example #9
0
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartContext) =>
            {
                INamedTypeSymbol mvcControllerSymbol     = WellKnownTypes.MvcController(compilationStartContext.Compilation);
                INamedTypeSymbol mvcControllerBaseSymbol = WellKnownTypes.MvcControllerBase(compilationStartContext.Compilation);
                INamedTypeSymbol actionResultSymbol      = WellKnownTypes.ActionResult(compilationStartContext.Compilation);

                if ((mvcControllerSymbol == null && mvcControllerBaseSymbol == null) || actionResultSymbol == null)
                {
                    // No MVC controllers that return an ActionResult here.
                    return;
                }

                MvcAttributeSymbols mvcAttributeSymbols = new MvcAttributeSymbols(compilationStartContext.Compilation);

                compilationStartContext.RegisterSymbolAction(
                    (SymbolAnalysisContext symbolContext) =>
                {
                    // TODO enhancements: Consider looking at non-ActionResult-derived return types as well.
                    IMethodSymbol methodSymbol = symbolContext.Symbol as IMethodSymbol;
                    if (methodSymbol == null ||
                        methodSymbol.MethodKind != MethodKind.Ordinary ||
                        methodSymbol.IsStatic ||
                        !methodSymbol.IsPublic() ||
                        !methodSymbol.ReturnType.Inherits(actionResultSymbol) ||          // FxCop implementation only looks at ActionResult-derived return types.
                        (!methodSymbol.ContainingType.Inherits(mvcControllerSymbol) &&
                         !methodSymbol.ContainingType.Inherits(mvcControllerBaseSymbol)))
                    {
                        return;
                    }

                    ImmutableArray <AttributeData> methodAttributes = methodSymbol.GetAttributes();
                    MvcHttpVerbs verbs;
                    bool isAntiforgeryTokenDefined;
                    bool isAction;
                    mvcAttributeSymbols.ComputeAttributeInfo(methodAttributes, out verbs, out isAntiforgeryTokenDefined, out isAction);

                    if (!isAction)
                    {
                        return;
                    }

                    if (verbs == MvcHttpVerbs.None)
                    {
                        // no verbs specified
                        if (isAntiforgeryTokenDefined)
                        {
                            // antiforgery token attribute is set, but verbs are not specified
                            symbolContext.ReportDiagnostic(Diagnostic.Create(NoVerbsRule, methodSymbol.Locations[0], methodSymbol.MetadataName));
                        }
                        else
                        {
                            // no verbs, no antiforgery token attribute
                            symbolContext.ReportDiagnostic(Diagnostic.Create(NoVerbsNoTokenRule, methodSymbol.Locations[0], methodSymbol.MetadataName));
                        }
                    }
                    else
                    {
                        // verbs are defined
                        if (isAntiforgeryTokenDefined)
                        {
                            if (verbs.HasFlag(MvcHttpVerbs.Get))
                            {
                                symbolContext.ReportDiagnostic(Diagnostic.Create(GetAndTokenRule, methodSymbol.Locations[0], methodSymbol.MetadataName));

                                if ((verbs & (MvcHttpVerbs.Post | MvcHttpVerbs.Put | MvcHttpVerbs.Delete | MvcHttpVerbs.Patch)) != MvcHttpVerbs.None)
                                {
                                    // both verbs, antiforgery token attribute
                                    symbolContext.ReportDiagnostic(Diagnostic.Create(GetAndOtherAndTokenRule, methodSymbol.Locations[0], methodSymbol.MetadataName));
                                }
                            }
                        }
                        else
                        {
                            if ((verbs & (MvcHttpVerbs.Post | MvcHttpVerbs.Put | MvcHttpVerbs.Delete | MvcHttpVerbs.Patch)) != MvcHttpVerbs.None)
                            {
                                // HttpPost, no antiforgery token attribute
                                symbolContext.ReportDiagnostic(Diagnostic.Create(VerbsAndNoTokenRule, methodSymbol.Locations[0], methodSymbol.MetadataName));
                            }
                        }
                    }
                },
                    SymbolKind.Method);
            }
                );
        }
            // CA1801: Remove unused parameters.
            // TODO: Remove the below suppression once Roslyn bug https://github.com/dotnet/roslyn/issues/8884 is fixed.
#pragma warning disable CA1801
            /// <summary>
            /// Checks rule: Ensure that {0} is declared as public and sealed.
            /// </summary>
            private static void CheckDisposeSignatureRule(IMethodSymbol method, INamedTypeSymbol type, SymbolAnalysisContext context)
#pragma warning restore CA1801
            {
                if (!method.IsPublic() ||
                    method.IsAbstract || method.IsVirtual || (method.IsOverride && !method.IsSealed))
                {
                    context.ReportDiagnostic(method.CreateDiagnostic(DisposeSignatureRule, $"{type.Name}.{method.Name}"));
                }
            }
 private static bool IsImplicitCastOperator(IMethodSymbol method, Compilation compilation)
 {
     if (!method.IsStatic || !method.IsPublic())
         return false;
     return (method.Name == WellKnownMemberNames.ImplicitConversionName);
 }
 private static bool IsEqualityOperator(IMethodSymbol method, Compilation compilation)
 {
     if (!method.IsStatic || !method.IsPublic())
         return false;
     switch (method.Name)
     {
         case WellKnownMemberNames.EqualityOperatorName:
         case WellKnownMemberNames.InequalityOperatorName:
             return true;
         default:
             return false;
     }
 }