From 6f20b92c479cd2e4e30139522987e74e4d3d50fa Mon Sep 17 00:00:00 2001 From: Srivatsn Narayanan Date: Thu, 19 Feb 2015 18:21:22 -0800 Subject: [PATCH] Moving CA1036 to System.Runtime.Analyzers. Also: - Make all analyzers cache the wellknown type by implementing compilationstart action. - Cleaning up the resx file in FxCopAnalyzers. --- .../Core/FxCopFixersResources.Designer.cs | 11 +- .../FxCop/Core/FxCopFixersResources.resx | 3 - .../Core/FxCopRulesDiagnosticAnalyzers.csproj | 1 - .../Core/FxCopRulesResources.Designer.cs | 36 ---- .../FxCop/Core/FxCopRulesResources.resx | 12 -- .../DefineAccessorsForAttributeArguments.cs | 19 ++- .../MarkAttributesWithAttributeUsage.cs | 43 ++--- .../OverrideMethodsOnComparableTypes.cs} | 54 +++--- ...atOwnDisposableFieldsShouldBeDisposable.cs | 31 ++-- .../Core/SystemRuntimeAnalyzers.csproj | 1 + ...ystemRuntimeAnalyzersResources.Designer.cs | 18 ++ .../Core/SystemRuntimeAnalyzersResources.resx | 6 + .../Core/WellKnownTypes.cs | 5 + .../OverrideMethodsOnComparableTypesTests.cs} | 156 +++++++++++++++++- ...ableFieldsShouldBeDisposableTests.Fixer.cs | 2 +- ...DisposableFieldsShouldBeDisposableTests.cs | 2 +- .../Test/SystemRuntimeAnalyzersTest.csproj | 1 + .../FxCopRulesDiagnosticAnalyzersTest.csproj | 1 - 18 files changed, 264 insertions(+), 138 deletions(-) rename src/Diagnostics/FxCop/{Core/Design/CA1036DiagnosticAnalyzer.cs => System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs} (64%) rename src/Diagnostics/FxCop/{Test/Design/CA1036Tests.cs => System.Runtime.Analyzers/Test/Design/OverrideMethodsOnComparableTypesTests.cs} (82%) diff --git a/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs b/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs index 632d2eb2f05..16f3d55ebed 100644 --- a/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs +++ b/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -159,15 +159,6 @@ internal class FxCopFixersResources { } } - /// - /// Looks up a localized string similar to Implement IDisposable Interface. - /// - internal static string ImplementIDisposableInterface { - get { - return ResourceManager.GetString("ImplementIDisposableInterface", resourceCulture); - } - } - /// /// Looks up a localized string similar to Implement Serialization constructor. /// diff --git a/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx b/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx index 13d10306a13..984a7d634de 100644 --- a/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx +++ b/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Implement IDisposable Interface - Overload operator equals on overriding ValueType.Equals diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj index 1895b313567..0fa6f3587b4 100644 --- a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj +++ b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj @@ -152,7 +152,6 @@ - diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs b/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs index 86128361dbe..f873ef430bb 100644 --- a/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs +++ b/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs @@ -195,15 +195,6 @@ internal class FxCopRulesResources { } } - /// - /// Looks up a localized string similar to Custom attributes should have AttributeUsage attribute defined.. - /// - internal static string CustomAttrShouldHaveAttributeUsage { - get { - return ResourceManager.GetString("CustomAttrShouldHaveAttributeUsage", resourceCulture); - } - } - /// /// Looks up a localized string similar to Disposable fields should be disposed. /// @@ -438,15 +429,6 @@ internal class FxCopRulesResources { } } - /// - /// Looks up a localized string similar to Specify AttributeUsage attribute on '{0}' attribute class.. - /// - internal static string MarkAttributesWithAttributeUsage { - get { - return ResourceManager.GetString("MarkAttributesWithAttributeUsage", resourceCulture); - } - } - /// /// Looks up a localized string similar to Mark Enum with FlagsAttribute. /// @@ -501,24 +483,6 @@ internal class FxCopRulesResources { } } - /// - /// Looks up a localized string similar to Overload operator Equals and comparison operators when implementing System.IComparable. - /// - internal static string OverloadOperatorEqualsOnIComparableInterface { - get { - return ResourceManager.GetString("OverloadOperatorEqualsOnIComparableInterface", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Types that implement IComparable should redefine Equals and comparison operators to keep the meanings of less than, greater than, and equals consistent throughout the type.. - /// - internal static string OverloadOperatorEqualsOnIComparableInterfaceDescription { - get { - return ResourceManager.GetString("OverloadOperatorEqualsOnIComparableInterfaceDescription", resourceCulture); - } - } - /// /// Looks up a localized string similar to Overload operator equals on overriding ValueType.Equals. /// diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx b/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx index 3da0489f0a7..3fce0ad6327 100644 --- a/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx +++ b/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx @@ -201,12 +201,6 @@ Implement Serialization constructor - - Specify AttributeUsage attribute on '{0}' attribute class. - - - Overload operator Equals and comparison operators when implementing System.IComparable - {0} '{1}' have identical names in a case-insensitive manner. @@ -216,9 +210,6 @@ Avoid unsealed attributes. - - Custom attributes should have AttributeUsage attribute defined. - Do not lock on objects with weak identity. @@ -315,9 +306,6 @@ The System.Runtime.Serialization.ISerializable interface allows the type to customize its serialization, while the Serializable attribute enables the runtime to recognize the type as being serializable. - - Types that implement IComparable should redefine Equals and comparison operators to keep the meanings of less than, greater than, and equals consistent throughout the type. - Value types that redefine System.ValueType.Equals should redefine the equality operator as well to ensure that these members return the same results. This helps ensure that types that rely on Equals (such as ArrayList and Hashtable) behave in a manner that is expected and consistent with the equality operator. diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/DefineAccessorsForAttributeArguments.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/DefineAccessorsForAttributeArguments.cs index 8b339c30894..da641c74a39 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/DefineAccessorsForAttributeArguments.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/DefineAccessorsForAttributeArguments.cs @@ -43,14 +43,23 @@ public override ImmutableArray SupportedDiagnostics public override void Initialize(AnalysisContext analysisContext) { - analysisContext.RegisterSymbolAction(context => + analysisContext.RegisterCompilationStartAction(compilationContext => { - AnalyzeSymbol((INamedTypeSymbol)context.Symbol, context.Compilation, context.ReportDiagnostic, context.Options, context.CancellationToken); - }, - SymbolKind.NamedType); + var attributeType = WellKnownTypes.IDisposable(compilationContext.Compilation); + if (attributeType == null) + { + return; + } + + compilationContext.RegisterSymbolAction(context => + { + AnalyzeSymbol((INamedTypeSymbol)context.Symbol, attributeType, context.Compilation, context.ReportDiagnostic); + }, + SymbolKind.NamedType); + }); } - private void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) + private void AnalyzeSymbol(INamedTypeSymbol symbol, INamedTypeSymbol attributeType, Compilation compilation, Action addDiagnostic) { if (symbol != null && symbol.GetBaseTypesAndThis().Contains(WellKnownTypes.Attribute(compilation)) && symbol.DeclaredAccessibility != Accessibility.Private) { diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAttributesWithAttributeUsage.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAttributesWithAttributeUsage.cs index 73276712f5d..1c9427e6f5f 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAttributesWithAttributeUsage.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAttributesWithAttributeUsage.cs @@ -28,42 +28,35 @@ public sealed class MarkAttributesWithAttributeUsageAnalyzer : DiagnosticAnalyze helpLinkUri: "http://msdn.microsoft.com/library/ms182158.aspx", customTags: WellKnownDiagnosticTags.Telemetry); - public override ImmutableArray SupportedDiagnostics - { - get - { - return ImmutableArray.Create(Rule); - } - } + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext analysisContext) { - analysisContext.RegisterSymbolAction(context => + analysisContext.RegisterCompilationStartAction(compilationContext => { - AnalyzeSymbol((INamedTypeSymbol)context.Symbol, context.Compilation, context.ReportDiagnostic, context.Options, context.CancellationToken); - }, - SymbolKind.NamedType); + var attributeType = WellKnownTypes.Attribute(compilationContext.Compilation); + var attributeUsageAttributeType = WellKnownTypes.AttributeUsageAttribute(compilationContext.Compilation); + if (attributeType == null || attributeUsageAttributeType == null) + { + return; + } + + compilationContext.RegisterSymbolAction(context => + { + AnalyzeSymbol((INamedTypeSymbol)context.Symbol, attributeType, attributeUsageAttributeType, context.ReportDiagnostic); + }, + SymbolKind.NamedType); + }); } - private static void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) + private static void AnalyzeSymbol(INamedTypeSymbol symbol, INamedTypeSymbol attributeType, INamedTypeSymbol attributeUsageAttributeType, Action addDiagnostic) { - var attributeUsageAttribute = WellKnownTypes.AttributeUsageAttribute(compilation); - if (attributeUsageAttribute == null) - { - return; - } - - if (symbol.IsAbstract || !symbol.GetBaseTypesAndThis().Contains(WellKnownTypes.Attribute(compilation))) - { - return; - } - - if (attributeUsageAttribute == null) + if (symbol.IsAbstract || !symbol.GetBaseTypesAndThis().Contains(attributeType)) { return; } - var hasAttributeUsageAttribute = symbol.GetAttributes().Any(attribute => attribute.AttributeClass == attributeUsageAttribute); + var hasAttributeUsageAttribute = symbol.GetAttributes().Any(attribute => attribute.AttributeClass == attributeUsageAttributeType); if (!hasAttributeUsageAttribute) { addDiagnostic(symbol.CreateDiagnostic(Rule, symbol.Name)); diff --git a/src/Diagnostics/FxCop/Core/Design/CA1036DiagnosticAnalyzer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs similarity index 64% rename from src/Diagnostics/FxCop/Core/Design/CA1036DiagnosticAnalyzer.cs rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs index 18fb4e84465..e3d5c1d3195 100644 --- a/src/Diagnostics/FxCop/Core/Design/CA1036DiagnosticAnalyzer.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs @@ -1,55 +1,63 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Immutable; using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities; -namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design +namespace System.Runtime.Analyzers { [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - public sealed class CA1036DiagnosticAnalyzer : AbstractNamedTypeAnalyzer + public sealed class OverrideMethodsOnComparableTypesAnalyzer : DiagnosticAnalyzer { internal const string RuleId = "CA1036"; - private static LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(FxCopRulesResources.OverloadOperatorEqualsOnIComparableInterface), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)); - private static LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(FxCopRulesResources.OverloadOperatorEqualsOnIComparableInterface), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)); - private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(FxCopRulesResources.OverloadOperatorEqualsOnIComparableInterfaceDescription), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)); + private static LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnIComparableInterface), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)); + private static LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnIComparableInterface), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)); + private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnIComparableInterfaceDescription), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)); internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId, s_localizableTitle, s_localizableMessage, - FxCopDiagnosticCategory.Design, + DiagnosticCategory.Design, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: s_localizableDescription, helpLinkUri: "http://msdn.microsoft.com/library/ms182163.aspx", - customTags: DiagnosticCustomTags.Microsoft); + customTags: WellKnownDiagnosticTags.Telemetry); - public override ImmutableArray SupportedDiagnostics + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext analysisContext) { - get + analysisContext.RegisterCompilationStartAction(compilationContext => { - return ImmutableArray.Create(Rule); - } - } + var comparableType = WellKnownTypes.IComparable(compilationContext.Compilation); + var genericComparableType = WellKnownTypes.GenericIComparable(compilationContext.Compilation); - protected override void AnalyzeSymbol(INamedTypeSymbol namedTypeSymbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) - { - var comparableType = WellKnownTypes.IComparable(compilation); + // Even if one of them is available, we should continue analysis. + if (comparableType == null && genericComparableType == null) + { + return; + } - if (comparableType == null) - { - return; - } + compilationContext.RegisterSymbolAction(context => + { + AnalyzeSymbol((INamedTypeSymbol)context.Symbol, comparableType, genericComparableType, context.ReportDiagnostic); + }, + SymbolKind.NamedType); + }); + } - if (namedTypeSymbol.DeclaredAccessibility == Accessibility.Private) + private static void AnalyzeSymbol(INamedTypeSymbol namedTypeSymbol, INamedTypeSymbol comparableType, INamedTypeSymbol genericComparableType, Action addDiagnostic) + { + if (namedTypeSymbol.DeclaredAccessibility == Accessibility.Private || namedTypeSymbol.TypeKind == TypeKind.Interface) { return; } - if (namedTypeSymbol.Interfaces.Contains(comparableType)) + if (namedTypeSymbol.AllInterfaces.Any(t => t.Equals(comparableType) || + (t.ConstructedFrom?.Equals(genericComparableType) ?? false))) { if (!(DoesOverrideEquals(namedTypeSymbol) && IsEqualityOperatorImplemented(namedTypeSymbol))) { diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs index 0ac28edff19..f6c643852c7 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs @@ -17,7 +17,6 @@ public sealed class TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer : Dia { internal const string RuleId = "CA1001"; internal const string Dispose = "Dispose"; - internal const string IDisposable = "System.IDisposable"; internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId, new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.TypesThatOwnDisposableFieldsShouldBeDisposable), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)), @@ -28,27 +27,29 @@ public sealed class TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer : Dia helpLinkUri: "http://msdn.microsoft.com/library/ms182172.aspx", customTags: WellKnownDiagnosticTags.Telemetry); - public override ImmutableArray SupportedDiagnostics - { - get - { - return ImmutableArray.Create(Rule); - } - } + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext analysisContext) { - analysisContext.RegisterSymbolAction(context => + analysisContext.RegisterCompilationStartAction(compilationContext => { - AnalyzeSymbol((INamedTypeSymbol)context.Symbol, context.Compilation, context.ReportDiagnostic, context.Options, context.CancellationToken); - }, - SymbolKind.NamedType); + var disposableType = WellKnownTypes.IDisposable(compilationContext.Compilation); + if (disposableType == null) + { + return; + } + + compilationContext.RegisterSymbolAction(context => + { + AnalyzeSymbol((INamedTypeSymbol)context.Symbol, disposableType, context.ReportDiagnostic); + }, + SymbolKind.NamedType); + }); } - private static void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) + private static void AnalyzeSymbol(INamedTypeSymbol symbol, INamedTypeSymbol disposableType, Action addDiagnostic) { - var disposableType = WellKnownTypes.IDisposable(compilation); - if (disposableType != null && !symbol.AllInterfaces.Contains(disposableType)) + if (!symbol.AllInterfaces.Contains(disposableType)) { var disposableFields = from member in symbol.GetMembers() where member.Kind == SymbolKind.Field && !member.IsStatic diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj index 25624a99a60..a92bdd0f1b2 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj @@ -53,6 +53,7 @@ + diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs index b8585faef2e..a103026ae59 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs @@ -187,6 +187,24 @@ internal class SystemRuntimeAnalyzersResources { } } + /// + /// Looks up a localized string similar to Overload operator Equals and comparison operators when implementing System.IComparable. + /// + internal static string OverloadOperatorEqualsOnIComparableInterface { + get { + return ResourceManager.GetString("OverloadOperatorEqualsOnIComparableInterface", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Types that implement IComparable should redefine Equals and comparison operators to keep the meanings of less than, greater than, and equals consistent throughout the type.. + /// + internal static string OverloadOperatorEqualsOnIComparableInterfaceDescription { + get { + return ResourceManager.GetString("OverloadOperatorEqualsOnIComparableInterfaceDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to Type '{0}' owns disposable fields but is not disposable. /// diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx index f5d50a0108e..29907925bfb 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx @@ -165,4 +165,10 @@ Remove the property setter from '{0}' or reduce its accessibility because it corresponds to positional argument '{1}'. + + Overload operator Equals and comparison operators when implementing System.IComparable + + + Types that implement IComparable should redefine Equals and comparison operators to keep the meanings of less than, greater than, and equals consistent throughout the type. + \ No newline at end of file diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs index 67904caa978..e1ca91e6513 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs @@ -141,6 +141,11 @@ public static INamedTypeSymbol IComparable(Compilation compilation) return compilation.GetTypeByMetadataName("System.IComparable"); } + public static INamedTypeSymbol GenericIComparable(Compilation compilation) + { + return compilation.GetTypeByMetadataName("System.IComparable`1"); + } + public static INamedTypeSymbol ComSourceInterfaceAttribute(Compilation compilation) { return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.ComSourceInterfacesAttribute"); diff --git a/src/Diagnostics/FxCop/Test/Design/CA1036Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/OverrideMethodsOnComparableTypesTests.cs similarity index 82% rename from src/Diagnostics/FxCop/Test/Design/CA1036Tests.cs rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/OverrideMethodsOnComparableTypesTests.cs index f93988e4823..5a814c83914 100644 --- a/src/Diagnostics/FxCop/Test/Design/CA1036Tests.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/OverrideMethodsOnComparableTypesTests.cs @@ -1,24 +1,24 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.FxCopAnalyzers.Design; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.UnitTests; using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.UnitTests +namespace System.Runtime.Analyzers.UnitTests { [WorkItem(858659, "DevDiv")] - public partial class CA1030Tests : DiagnosticAnalyzerTestBase + public partial class OverrideMethodsOnComparableTypesTests : DiagnosticAnalyzerTestBase { protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { - return new CA1036DiagnosticAnalyzer(); + return new OverrideMethodsOnComparableTypesAnalyzer(); } protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { - return new CA1036DiagnosticAnalyzer(); + return new OverrideMethodsOnComparableTypesAnalyzer(); } [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] @@ -397,6 +397,82 @@ public override bool Equals(object obj) GetCA1036CSharpResultAt(4, 19)); } + [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] + public void CA1036ClassWithGenericIComparableCSharp() + { + VerifyCSharp(@" + using System; + + public class A : IComparable + { + public override int GetHashCode() + { + return 1234; + } + + public int CompareTo(int obj) + { + return 1; + } + + public override bool Equals(object obj) + { + return true; + } + + public static bool operator <(A objLeft, A objRight) + { + return true; + } + + public static bool operator >(A objLeft, A objRight) + { + return true; + } + } +", + GetCA1036CSharpResultAt(4, 18)); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] + public void CA1036ClassWithDerivedIComparableCSharp() + { + VerifyCSharp(@" + using System; + + interface IDerived : IComparable { } + + public class A : IDerived + { + public override int GetHashCode() + { + return 1234; + } + + public int CompareTo(int obj) + { + return 1; + } + + public override bool Equals(object obj) + { + return true; + } + + public static bool operator <(A objLeft, A objRight) + { + return true; + } + + public static bool operator >(A objLeft, A objRight) + { + return true; + } + } +", + GetCA1036CSharpResultAt(6, 18)); + } + [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] public void CA1036ClassNoWarningBasic() { @@ -723,6 +799,76 @@ End Class GetCA1036BasicResultAt(4, 18)); } + [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] + public void CA1036ClassWithGenericIComparableBasic() + { + VerifyBasic(@" +Imports System + +Public Structure A : Implements IComparable(Of Integer) + + Public Function Overrides GetHashCode() As Integer + Return 1234 + End Function + + Public Function CompareTo(obj As Integer) As Integer + Return 1 + End Function + + Public Overloads Overrides Function Equals(obj As Object) As Boolean + Return True + End Function + + Public Shared Operator =(objLeft As A, objRight As A) As Boolean + Return True + End Operator + + Public Shared Operator <>(objLeft As A, objRight As A) As Boolean + Return True + End Operator + +End Class +", + GetCA1036BasicResultAt(4, 18)); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)] + public void CA1036ClassWithDerivedIComparableBasic() + { + VerifyBasic(@" +Imports System + +Public Interface IDerived + Inherits IComparable(Of Integer) +End Interface + +Public Structure A : Implements IDerived + + Public Function Overrides GetHashCode() As Integer + Return 1234 + End Function + + Public Function CompareTo(obj As Object) As Integer + Return 1 + End Function + + Public Overloads Overrides Function Equals(obj As Object) As Boolean + Return True + End Function + + Public Shared Operator =(objLeft As A, objRight As A) As Boolean + Return True + End Operator + + Public Shared Operator <>(objLeft As A, objRight As A) As Boolean + Return True + End Operator + +End Class +", + GetCA1036BasicResultAt(8, 18)); + } + internal static string CA1036Name = "CA1036"; internal static string CA1036Message = "Overload operator Equals and comparison operators when implementing System.IComparable"; diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs index 10486b4b4cc..c735e3cc50d 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs @@ -8,7 +8,7 @@ namespace System.Runtime.Analyzers.UnitTests { - public partial class CA1001FixerTests : CodeFixTestBase + public partial class TypesThatOwnDisposableFieldsShouldBeDisposableFixerTests : CodeFixTestBase { protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs index 540ca3d31fc..807c0ca4b65 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs @@ -7,7 +7,7 @@ namespace System.Runtime.Analyzers.UnitTests { - public partial class CA1001Tests : DiagnosticAnalyzerTestBase + public partial class TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzerTests : DiagnosticAnalyzerTestBase { protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj index b05bf5eedfa..8f7ad581799 100644 --- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj +++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj @@ -97,6 +97,7 @@ + diff --git a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj index fc5084791bd..0283e115f80 100644 --- a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj +++ b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj @@ -106,7 +106,6 @@ - -- GitLab