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