private static bool HasCandidateSignature(IMethodSymbol method) =>
 method.IsPubliclyAccessible() &&
 method.Parameters.Length == 0 &&
 !method.IsConstructor() &&
 !method.IsOverride &&
 method.MethodKind != MethodKind.PropertyGet &&
 method.GetInterfaceMember() is null;
        private static string GetCodeFixTitle(
            string resourceString,
            IMethodSymbol methodToUpdate,
            bool includeParameters
            )
        {
            var methodDisplay = methodToUpdate.ToDisplayString(
                new SymbolDisplayFormat(
                    typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes,
                    extensionMethodStyle: SymbolDisplayExtensionMethodStyle.StaticMethod,
                    parameterOptions: SymbolDisplayParameterOptions.None,
                    memberOptions: methodToUpdate.IsConstructor()
                      ? SymbolDisplayMemberOptions.None
                      : SymbolDisplayMemberOptions.IncludeContainingType
                    )
                );

            var parameters = methodToUpdate.Parameters.Select(p => p.ToDisplayString(SimpleFormat));
            var signature  = includeParameters
                ? $"{methodDisplay}({string.Join(", ", parameters)})"
                : methodDisplay;
            var title = string.Format(resourceString, signature);

            return(title);
        }
        private static async Task <Document> SetAccessibilityAsync(Document document, IMethodSymbol methodSymbol, CancellationToken cancellationToken)
        {
            SymbolEditor editor = SymbolEditor.Create(document);

            // This would be constructor and can have only one definition.
            Debug.Assert(methodSymbol.IsConstructor() && methodSymbol.DeclaringSyntaxReferences.HasExactly(1));
            await editor.EditOneDeclarationAsync(methodSymbol, (docEditor, declaration) =>
            {
                Accessibility newAccessibility = methodSymbol.ContainingType.IsSealed ? Accessibility.Private : Accessibility.Protected;
                docEditor.SetAccessibility(declaration, newAccessibility);
            }, cancellationToken).ConfigureAwait(false);

            return(editor.GetChangedDocuments().First());
        }
        private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation)
        {
            // Modifiers that we don't care about
            if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual ||
                methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember())
            {
                return(false);
            }

            if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer())
            {
                return(false);
            }

            // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases.
            if (methodSymbol.ContainingType.IsGenericType && methodSymbol.IsExternallyVisible())
            {
                return(false);
            }

            // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same.
            var skipAttributes = new[]
            {
                "WebMethodAttribute",
                "TestInitializeAttribute",
                "TestMethodAttribute",
                "TestCleanupAttribute",
            };

            if (methodSymbol.GetAttributes().Any(attribute => skipAttributes.Contains(attribute.AttributeClass.Name)))
            {
                return(false);
            }

            // If this looks like an event handler don't flag such cases.
            if (methodSymbol.Parameters.Length == 2 &&
                methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                IsEventArgs(methodSymbol.Parameters[1].Type, compilation))
            {
                return(false);
            }

            if (IsExplicitlyVisibleFromCom(methodSymbol, compilation))
            {
                return(false);
            }

            return(true);
        }
        private bool IsPropertyCanditate(IMethodSymbol method)
        {
            if (method.IsConstructor() ||
                method.MethodKind == MethodKind.PropertyGet ||
                method.IsOverride ||
                IsInherited(method))
            {
                return(false);
            }

            return(method.Parameters.Length == 0 &&
                   !method.ReturnsVoid &&
                   !method.ReturnType.Is(TypeKind.Array) &&
                   NameStartsWithGet(method));
        }
        private bool IsPropertyCanditate(IMethodSymbol method)
        {
            if (method.IsConstructor() ||
                method.MethodKind == MethodKind.PropertyGet ||
                method.IsOverride ||
                method.GetInterfaceMember() != null)
            {
                return(false);
            }

            return(method.Parameters.Length == 0 &&
                   !method.ReturnsVoid &&
                   !method.ReturnType.Is(TypeKind.Array) &&
                   method.Name != "GetEnumerator" &&
                   NameStartsWithGet(method));
        }
Example #7
0
 public override SyntaxNode CreateMethodDeclaration(
     IMethodSymbol method, CodeGenerationDestination destination, CodeGenerationOptions options)
 {
     if (method.IsConstructor())
     {
         return(ConstructorGenerator.GenerateConstructorDeclaration(method, destination, options));
     }
     else if (method.IsDestructor())
     {
         return(DestructorGenerator.GenerateDestructorDeclaration(method, destination, options));
     }
     else
     {
         return(MethodGenerator.GenerateMethodDeclaration(method, destination, options));
     }
 }
Example #8
0
        private static bool IsSkippedMethod(IMethodSymbol methodSymbol, WellKnownTypeProvider wellKnownTypeProvider)
        {
            if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer())
            {
                return(true);
            }

            if (methodSymbol.ReturnsVoid &&
                methodSymbol.Parameters.IsEmpty &&
                (methodSymbol.Name == "Application_Start" || methodSymbol.Name == "Application_End") &&
                methodSymbol.ContainingType.Inherits(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebHttpApplication)))
            {
                return(true);
            }

            return(false);
        }
        protected override bool ShallAnalyzeMethod(IMethodSymbol symbol)
        {
            if (symbol.IsConstructor() is false)
            {
                return(false);
            }

            if (IsParameterlessCtor(symbol) ||
                IsMessageCtor(symbol) ||
                IsMessageExceptionCtor(symbol) ||
                symbol.IsSerializationConstructor())
            {
                return(symbol.GetDocumentationCommentXml().IsNullOrWhiteSpace() is false);
            }

            return(false); // unknown ctor
        }
Example #10
0
        protected override bool ShallAnalyze(IMethodSymbol symbol)
        {
            if (symbol.IsConstructor())
            {
                return(false);
            }

            switch (symbol.DeclaredAccessibility)
            {
            case Accessibility.NotApplicable:
            case Accessibility.Private:
                return(false);    // ignore private methods or those that don't have any accessibility (means they are also private)

            default:
                return(base.ShallAnalyze(symbol));
            }
        }
Example #11
0
        public override SyntaxNode CreateMethodDeclaration(
            IMethodSymbol method, CodeGenerationDestination destination, CodeGenerationOptions options)
        {
            // Synthesized methods for properties/events are not things we actually generate
            // declarations for.
            if (method.AssociatedSymbol is IEventSymbol)
            {
                return(null);
            }

            if (method.AssociatedSymbol is IPropertySymbol)
            {
                // we will ignore the method if the associated property can be generated.
                var property = (IPropertySymbol)method.AssociatedSymbol;
                if (PropertyGenerator.CanBeGenerated(property))
                {
                    return(null);
                }
            }

            if (method.IsConstructor())
            {
                return(ConstructorGenerator.GenerateConstructorDeclaration(
                           method, destination, Workspace, options, options.ParseOptions));
            }
            else if (method.IsDestructor())
            {
                return(DestructorGenerator.GenerateDestructorDeclaration(method, destination, options));
            }
            else if (method.IsUserDefinedOperator())
            {
                return(OperatorGenerator.GenerateOperatorDeclaration(
                           method, destination, Workspace, options, options.ParseOptions));
            }
            else if (method.IsConversion())
            {
                return(ConversionGenerator.GenerateConversionDeclaration(
                           method, destination, Workspace, options, options.ParseOptions));
            }
            else
            {
                return(MethodGenerator.GenerateMethodDeclaration(
                           method, destination, Workspace, options, options.ParseOptions));
            }
        }
        private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation, ImmutableArray <INamedTypeSymbol> skippedAttributes)
        {
            // Modifiers that we don't care about
            if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual ||
                methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember())
            {
                return(false);
            }

            if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer())
            {
                return(false);
            }

            // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases.
            if (methodSymbol.ContainingType.IsGenericType && methodSymbol.IsExternallyVisible())
            {
                return(false);
            }

            // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same.
            if (methodSymbol.GetAttributes().Any(attribute => skippedAttributes.Any(attr => attribute.AttributeClass.Inherits(attr))))
            {
                return(false);
            }

            // If this looks like an event handler don't flag such cases.
            // However, we do want to consider EventRaise accessor as a candidate
            // so we can flag the associated event if none of it's accessors need instance reference.
            if (methodSymbol.Parameters.Length == 2 &&
                methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                IsEventArgs(methodSymbol.Parameters[1].Type, compilation) &&
                methodSymbol.MethodKind != MethodKind.EventRaise)
            {
                return(false);
            }

            if (IsExplicitlyVisibleFromCom(methodSymbol, compilation))
            {
                return(false);
            }

            return(true);
        }
Example #13
0
        private bool IsPropertyCanditate(IMethodSymbol method)
        {
            if (method.IsConstructor() ||
                method.MethodKind == MethodKind.PropertyGet ||
                method.IsOverride ||
                method.GetInterfaceMember() != null ||
                method.IsAsync ||
                method.ReturnType.OriginalDefinition.IsAny(KnownType.SystemTasks))
            {
                return(false);
            }

            return(method.Parameters.Length == 0 &&
                   !method.ReturnsVoid &&
                   !method.ReturnType.Is(TypeKind.Array) &&
                   method.Name != "GetEnumerator" &&
                   method.Name != "GetAwaiter" &&
                   NameStartsWithGet(method));
        }
Example #14
0
        public bool HasCascadingDeclarations(IMethodSymbol method)
        {
            // Don't cascade constructors
            if (method.IsConstructor())
            {
                return(false);
            }

            // Virtual methods of all kinds might have overrides somewhere else that need to be fixed.
            if (method.IsVirtual || method.IsOverride || method.IsAbstract)
            {
                return(true);
            }

            // If interfaces are involved we will fix those too
            // Explicit interface implementations are easy to detect
            if (method.ExplicitInterfaceImplementations.Length > 0)
            {
                return(true);
            }

            // For implicit interface implementations lets check if the characteristic of the method
            // allows it to implicit implement an interface member.
            if (method.DeclaredAccessibility != Accessibility.Public)
            {
                return(false);
            }

            if (method.IsStatic)
            {
                return(false);
            }

            // Now check if the method does implement an interface member
            if (method.ExplicitOrImplicitInterfaceImplementations().Length > 0)
            {
                return(true);
            }

            return(false);
        }
Example #15
0
        static string ToMethodCode(this IMethodSymbol symbol, string modifiers)
        {
            var code = new StringBuilder(150);

            if (symbol.ContainingType.IsInterface())
            {
                modifiers = "";
            }

            string returnTypeAndName;
            var    returnType = symbol.OriginalDefinition.ReturnType.ToMinimalString();

            if (symbol.IsConstructor())
            {
                returnTypeAndName = $"{symbol.ContainingType.Name}";        // Printer
            }
            else if (symbol.IsDestructor())
            {
                returnTypeAndName = $"~{symbol.ContainingType.Name}";       // ~Printer
            }
            else if (symbol.IsOperator())
            {
                returnTypeAndName = $"{returnType} {symbol.GetDisplayName()}";  // operator T? (T value);
            }
            else if (symbol.IsConversion())
            {
                returnTypeAndName = $"{symbol.GetDisplayName()} {returnType}";  //  implicit operator DBBool(bool x)
            }
            else
            {
                returnTypeAndName = $"{returnType} {symbol.Name}";              //int GetIndex
            }
            code.Append($"{modifiers.Trim()} ")                                 // public static
            .Append(returnTypeAndName)                                          // int GetIndex
            .Append(symbol.TypeParameters.ToDeclarationString())                // <T, T2>
            .Append(symbol.GetParametersString())                               //(int position, int value)
            .Append(symbol.TypeParameters.GetConstrains(singleLine: true))      // where T: class
            .Append(";");

            return(code.ToString());
        }
        private static bool CanBeIgnored(IMethodSymbol method)
        {
            if (method is null)
            {
                return(false);
            }

            if (method.IsOverride || method.IsVirtual)
            {
                return(true);
            }

            if (method.IsConstructor())
            {
                return(method.IsSerializationConstructor());
            }

            if (method.IsEventHandler())
            {
                return(true);
            }

            if (method.IsDependencyPropertyEventHandler())
            {
                return(true);
            }

            if (method.IsCoerceValueCallback())
            {
                return(true);
            }

            if (method.IsValidateValueCallback())
            {
                return(true);
            }

            var ignore = method.IsInterfaceImplementation();

            return(ignore);
        }
Example #17
0
            private SuppressFinalizeUsage GetAllowedSuppressFinalizeUsage(IMethodSymbol method)
            {
                // We allow constructors in sealed types to call GC.SuppressFinalize.
                // This allows types that derive from Component (such SqlConnection)
                // to prevent the finalizer they inherit from Component from ever
                // being called.
                if (method.ContainingType.IsSealed && method.IsConstructor() && !method.IsStatic)
                {
                    return(SuppressFinalizeUsage.CanCall);
                }

                if (!method.IsDisposeImplementation(_compilation))
                {
                    return(SuppressFinalizeUsage.MustNotCall);
                }

                // If the Dispose method is declared in a sealed type, we do
                // not require that the method calls GC.SuppressFinalize
                var hasFinalizer = method.ContainingType.HasFinalizer();

                if (method.ContainingType.IsSealed && !hasFinalizer)
                {
                    return(SuppressFinalizeUsage.CanCall);
                }

                // We don't require that non-public types call GC.SuppressFinalize
                // if they don't have a finalizer as the owner of the assembly can
                // control whether any finalizable types derive from them.
                if (method.ContainingType.DeclaredAccessibility != Accessibility.Public && !hasFinalizer)
                {
                    return(SuppressFinalizeUsage.CanCall);
                }

                // Even if the Dispose method is declared on a type without a
                // finalizer, we still require it to call GC.SuppressFinalize to
                // prevent derived finalizable types from having to reimplement
                // IDisposable.Dispose just to call it.
                return(SuppressFinalizeUsage.MustCall);
            }
        protected override TDeclarationNode AddMethod <TDeclarationNode>(TDeclarationNode destination, IMethodSymbol method, CodeGenerationOptions options, IList <bool> availableIndices)
        {
            CheckDeclarationNode <TypeDeclarationSyntax, CompilationUnitSyntax, NamespaceDeclarationSyntax>(destination);

            // Synthesized methods for properties/events are not things we actually generate
            // declarations for.
            if (method.AssociatedSymbol is IEventSymbol)
            {
                return(destination);
            }
            // we will ignore the method if the associated property can be generated.

            if (method.AssociatedSymbol is IPropertySymbol property)
            {
                if (PropertyGenerator.CanBeGenerated(property))
                {
                    return(destination);
                }
            }

            if (destination is TypeDeclarationSyntax typeDeclaration)
            {
                if (method.IsConstructor())
                {
                    return(Cast <TDeclarationNode>(ConstructorGenerator.AddConstructorTo(
                                                       typeDeclaration, method, Workspace, options, availableIndices)));
                }

                if (method.IsDestructor())
                {
                    return(Cast <TDeclarationNode>(DestructorGenerator.AddDestructorTo(typeDeclaration, method, options, availableIndices)));
                }

                if (method.MethodKind == MethodKind.Conversion)
                {
                    return(Cast <TDeclarationNode>(ConversionGenerator.AddConversionTo(
                                                       typeDeclaration, method, Workspace, options, availableIndices)));
                }

                if (method.MethodKind == MethodKind.UserDefinedOperator)
                {
                    return(Cast <TDeclarationNode>(OperatorGenerator.AddOperatorTo(
                                                       typeDeclaration, method, Workspace, options, availableIndices)));
                }

                return(Cast <TDeclarationNode>(MethodGenerator.AddMethodTo(
                                                   typeDeclaration, method, Workspace, options, availableIndices)));
            }

            if (method.IsConstructor() ||
                method.IsDestructor())
            {
                return(destination);
            }

            if (destination is CompilationUnitSyntax compilationUnit)
            {
                return(Cast <TDeclarationNode>(
                           MethodGenerator.AddMethodTo(compilationUnit, method, Workspace, options, availableIndices)));
            }

            var ns = Cast <NamespaceDeclarationSyntax>(destination);

            return(Cast <TDeclarationNode>(
                       MethodGenerator.AddMethodTo(ns, method, Workspace, options, availableIndices)));
        }
            private SuppressFinalizeUsage GetAllowedSuppressFinalizeUsage(IMethodSymbol method)
            {
                // We allow constructors in sealed types to call GC.SuppressFinalize.
                // This allows types that derive from Component (such SqlConnection)
                // to prevent the finalizer they inherit from Component from ever
                // being called.
                if (method.ContainingType.IsSealed && method.IsConstructor() && !method.IsStatic)
                {
                    return SuppressFinalizeUsage.CanCall;
                }

                if (!method.IsDisposeImplementation(_compilation))
                {
                    return SuppressFinalizeUsage.MustNotCall;
                }

                // If the Dispose method is declared in a sealed type, we do
                // not require that the method calls GC.SuppressFinalize
                var hasFinalizer = method.ContainingType.HasFinalizer();
                if (method.ContainingType.IsSealed && !hasFinalizer)
                {
                    return SuppressFinalizeUsage.CanCall;
                }

                // We don't require that non-public types call GC.SuppressFinalize
                // if they don't have a finalizer as the owner of the assembly can
                // control whether any finalizable types derive from them.
                if (method.ContainingType.DeclaredAccessibility != Accessibility.Public && !hasFinalizer)
                {
                    return SuppressFinalizeUsage.CanCall;
                }

                // Even if the Dispose method is declared on a type without a
                // finalizer, we still require it to call GC.SuppressFinalize to
                // prevent derived finalizable types from having to reimplement
                // IDisposable.Dispose just to call it.
                return SuppressFinalizeUsage.MustCall;
            }
Example #20
0
        protected override TDeclarationNode AddMethod <TDeclarationNode>(TDeclarationNode destination, IMethodSymbol method, CodeGenerationOptions options, IList <bool> availableIndices)
        {
            // https://github.com/dotnet/roslyn/issues/44425: Add handling for top level statements
            if (destination is GlobalStatementSyntax)
            {
                return(destination);
            }

            CheckDeclarationNode <TypeDeclarationSyntax, CompilationUnitSyntax, BaseNamespaceDeclarationSyntax>(destination);

            options = options.With(options: options.Options ?? Workspace.Options);

            // Synthesized methods for properties/events are not things we actually generate
            // declarations for.
            if (method.AssociatedSymbol is IEventSymbol)
            {
                return(destination);
            }
            // we will ignore the method if the associated property can be generated.

            if (method.AssociatedSymbol is IPropertySymbol property)
            {
                if (PropertyGenerator.CanBeGenerated(property))
                {
                    return(destination);
                }
            }

            if (destination is TypeDeclarationSyntax typeDeclaration)
            {
                if (method.IsConstructor())
                {
                    return(Cast <TDeclarationNode>(ConstructorGenerator.AddConstructorTo(
                                                       typeDeclaration, method, options, availableIndices)));
                }

                if (method.IsDestructor())
                {
                    return(Cast <TDeclarationNode>(DestructorGenerator.AddDestructorTo(typeDeclaration, method, options, availableIndices)));
                }

                if (method.MethodKind == MethodKind.Conversion)
                {
                    return(Cast <TDeclarationNode>(ConversionGenerator.AddConversionTo(
                                                       typeDeclaration, method, options, availableIndices)));
                }

                if (method.MethodKind == MethodKind.UserDefinedOperator)
                {
                    return(Cast <TDeclarationNode>(OperatorGenerator.AddOperatorTo(
                                                       typeDeclaration, method, options, availableIndices)));
                }

                return(Cast <TDeclarationNode>(MethodGenerator.AddMethodTo(
                                                   typeDeclaration, method, options, availableIndices)));
            }

            if (method.IsConstructor() ||
                method.IsDestructor())
            {
                return(destination);
            }

            if (destination is CompilationUnitSyntax compilationUnit)
            {
                return(Cast <TDeclarationNode>(
                           MethodGenerator.AddMethodTo(compilationUnit, method, options, availableIndices)));
            }

            var ns = Cast <BaseNamespaceDeclarationSyntax>(destination);

            return(Cast <TDeclarationNode>(
                       MethodGenerator.AddMethodTo(ns, method, options, availableIndices)));
        }
 protected override bool ShallAnalyze(IMethodSymbol symbol) => symbol.IsConstructor();
Example #22
0
 /// <summary>
 /// Indicates if the current method is a constructor (normal, static, shared) or a destructor
 /// </summary>
 /// <param name="currentMethod">The current method</param>
 /// <returns>True if the current method is a constructor or a destructor</returns>
 public static bool IsConstructorOrDestructor(this IMethodSymbol currentMethod) => currentMethod.IsConstructor() || currentMethod.IsDestructor();
        private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation)
        {
            // Modifiers that we don't care about
            if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual ||
                methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember())
            {
                return false;
            }

            if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer())
            {
                return false;
            }
            
            // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases.
            if (methodSymbol.ContainingType.IsGenericType && methodSymbol.GetResultantVisibility() == SymbolVisibility.Public)
            {
                return false;
            }

            // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same.
            var skipAttributes = new[]
            {
                "WebMethodAttribute",
                "TestInitializeAttribute",
                "TestMethodAttribute",
                "TestCleanupAttribute",
            };

            if (methodSymbol.GetAttributes().Any(attribute => skipAttributes.Contains(attribute.AttributeClass.Name)))
            {
                return false;
            }

            // If this looks like an event handler don't flag such cases.
            if (methodSymbol.Parameters.Length == 2 && 
                methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                IsEventArgs(methodSymbol.Parameters[1].Type, compilation))
            {
                return false;
            }

            if (IsExplicitlyVisibleFromCom(methodSymbol, compilation))
            {
                return false;
            }

            return true;
        }