/// <summary>
        /// Checks if a given method implements IEqualityComparer.Equals or IEquatable.Equals.
        /// </summary>
        private static bool IsEqualsInterfaceImplementation(IMethodSymbol method, Compilation compilation)
        {
            if (method.Name != WellKnownMemberNames.ObjectEquals)
            {
                return(false);
            }

            int paramCount = method.Parameters.Length;

            if (method.ReturnType.SpecialType == SpecialType.System_Boolean &&
                (paramCount == 1 || paramCount == 2))
            {
                // Substitute the type of the first parameter of Equals in the generic interface and then check if that
                // interface method is implemented by the given method.
                INamedTypeSymbol iEqualityComparer = WellKnownTypes.GenericIEqualityComparer(compilation);
                if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEqualityComparer, WellKnownMemberNames.ObjectEquals))
                {
                    return(true);
                }

                // Substitute the type of the first parameter of Equals in the generic interface and then check if that
                // interface method is implemented by the given method.
                INamedTypeSymbol iEquatable = WellKnownTypes.GenericIEquatable(compilation);
                if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEquatable, WellKnownMemberNames.ObjectEquals))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 2
0
        private static void OnCompilationStart(CompilationStartAnalysisContext context)
        {
            INamedTypeSymbol objectType    = context.Compilation.GetSpecialType(SpecialType.System_Object);
            INamedTypeSymbol equatableType = WellKnownTypes.GenericIEquatable(context.Compilation);

            if (objectType != null && equatableType != null)
            {
                context.RegisterSymbolAction(c => AnalyzeSymbol(c, equatableType), SymbolKind.NamedType);
            }
        }
Esempio n. 3
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxGenerator generator = SyntaxGenerator.GetGenerator(context.Document);
            SyntaxNode      root      = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            SyntaxNode declaration = root.FindNode(context.Span);

            declaration = generator.GetDeclaration(declaration);
            if (declaration == null)
            {
                return;
            }

            SemanticModel model =
                await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            INamedTypeSymbol type = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;

            if (type == null || type.TypeKind != TypeKind.Class && type.TypeKind != TypeKind.Struct)
            {
                return;
            }

            INamedTypeSymbol equatableType = WellKnownTypes.GenericIEquatable(model.Compilation);

            if (equatableType == null)
            {
                return;
            }

            // We cannot have multiple overlapping diagnostics of this id.
            Diagnostic diagnostic = context.Diagnostics.Single();

            if (type.TypeKind == TypeKind.Struct && !TypeImplementsEquatable(type, equatableType))
            {
                string title = MicrosoftApiDesignGuidelinesAnalyzersResources.ImplementEquatable;
                context.RegisterCodeFix(new MyCodeAction(
                                            title,
                                            async ct =>
                                            await ImplementEquatableInStructAsync(context.Document, declaration, type, model.Compilation,
                                                                                  equatableType, ct).ConfigureAwait(false),
                                            equivalenceKey: title), diagnostic);
            }

            if (!type.OverridesEquals())
            {
                string title = MicrosoftApiDesignGuidelinesAnalyzersResources.OverrideEqualsOnImplementingIEquatableCodeActionTitle;
                context.RegisterCodeFix(new MyCodeAction(
                                            title,
                                            async ct =>
                                            await OverrideObjectEqualsAsync(context.Document, declaration, type, equatableType,
                                                                            ct).ConfigureAwait(false),
                                            equivalenceKey: title), diagnostic);
            }
        }
 private WellKnownTypeProvider(Compilation compilation)
 {
     Compilation       = compilation;
     Exception         = WellKnownTypes.Exception(compilation);
     Contract          = WellKnownTypes.SystemDiagnosticContractsContract(compilation);
     IDisposable       = WellKnownTypes.IDisposable(compilation);
     Task              = WellKnownTypes.Task(compilation);
     CollectionTypes   = GetWellKnownCollectionTypes(compilation);
     SerializationInfo = WellKnownTypes.SerializationInfo(compilation);
     GenericIEquatable = WellKnownTypes.GenericIEquatable(compilation);
 }