/// <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); }
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, });
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); }
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); }
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; } }