diff --git a/src/Diagnostics/FxCop/CSharp/CSharpFxCopRulesDiagnosticAnalyzers.csproj b/src/Diagnostics/FxCop/CSharp/CSharpFxCopRulesDiagnosticAnalyzers.csproj
index d89c621505a06..c3a86e3feb049 100644
--- a/src/Diagnostics/FxCop/CSharp/CSharpFxCopRulesDiagnosticAnalyzers.csproj
+++ b/src/Diagnostics/FxCop/CSharp/CSharpFxCopRulesDiagnosticAnalyzers.csproj
@@ -86,7 +86,6 @@
-
diff --git a/src/Diagnostics/FxCop/CSharp/Usage/CodeFixes/CA2231CSharpCodeFixProvider.cs b/src/Diagnostics/FxCop/CSharp/Usage/CodeFixes/CA2231CSharpCodeFixProvider.cs
deleted file mode 100644
index dd76b3044c667..0000000000000
--- a/src/Diagnostics/FxCop/CSharp/Usage/CodeFixes/CA2231CSharpCodeFixProvider.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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.Composition;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CodeGeneration;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Usage;
-
-namespace Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Usage
-{
- ///
- /// CA2231: Overload operator equals on overriding ValueType.Equals
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = CA2231DiagnosticAnalyzer.RuleId), Shared]
- public class CA2231CSharpCodeFixProvider : CA2231CodeFixProviderBase
- {
- internal override Task GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
- {
- //// We are going to add two operators:
- ////
- //// public static bool operator ==(A left, A right)
- //// {
- //// throw new NotImplementedException();
- //// }
- ////
- //// public static bool operator !=(A left, A right)
- //// {
- //// throw new NotImplementedException();
- //// }
-
- var syntaxNode = nodeToFix as StructDeclarationSyntax;
- if (syntaxNode == null)
- {
- return Task.FromResult(document);
- }
-
- var statement = CreateThrowNotImplementedStatement(model);
- if (statement == null)
- {
- return Task.FromResult(document);
- }
-
- var parameters = new[] { CreateParameter(syntaxNode.Identifier.ValueText, LeftName), CreateParameter(syntaxNode.Identifier.ValueText, RightName) };
-
- var op_equality = CreateOperatorDeclaration(SyntaxKind.EqualsEqualsToken, parameters, statement);
- var op_inequality = CreateOperatorDeclaration(SyntaxKind.ExclamationEqualsToken, parameters, statement);
- var newNode = syntaxNode.AddMembers(new[] { op_equality, op_inequality }).WithAdditionalAnnotations(Formatter.Annotation);
-
- return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(nodeToFix, newNode)));
- }
-
- protected StatementSyntax CreateThrowNotImplementedStatement(SemanticModel model)
- {
- var exceptionType = model.Compilation.GetTypeByMetadataName(NotImplementedExceptionName);
- if (exceptionType == null)
- {
- // If we can't find the exception, we can't generate anything.
- return null;
- }
-
- return SyntaxFactory.ThrowStatement(
- SyntaxFactory.ObjectCreationExpression(
- SyntaxFactory.Token(SyntaxKind.NewKeyword),
- SyntaxFactory.IdentifierName(exceptionType.Name),
- SyntaxFactory.ArgumentList(),
- null));
- }
-
- protected ParameterSyntax CreateParameter(string type, string name)
- {
- return SyntaxFactory.Parameter(
- new SyntaxList(),
- SyntaxFactory.TokenList(),
- SyntaxFactory.ParseTypeName(type),
- SyntaxFactory.IdentifierName(name).Identifier,
- null);
- }
-
- protected OperatorDeclarationSyntax CreateOperatorDeclaration(SyntaxKind kind, ParameterSyntax[] parameters, StatementSyntax statement)
- {
- return SyntaxFactory.OperatorDeclaration(
- new SyntaxList(),
- SyntaxFactory.TokenList(new SyntaxToken[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword) }),
- SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BoolKeyword)),
- SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
- SyntaxFactory.Token(kind),
- SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters)),
- SyntaxFactory.Block(statement),
- new SyntaxToken());
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs b/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs
index 16f3d55ebeda8..07d21497a5580 100644
--- a/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs
+++ b/src/Diagnostics/FxCop/Core/FxCopFixersResources.Designer.cs
@@ -177,15 +177,6 @@ internal static string MarkEnumsWithFlagsCodeFix {
}
}
- ///
- /// Looks up a localized string similar to Overload operator equals on overriding ValueType.Equals.
- ///
- internal static string OverloadOperatorEqualsOnOverridingValueTypeEquals {
- get {
- return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEquals", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Remove empty finalizers.
///
diff --git a/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx b/src/Diagnostics/FxCop/Core/FxCopFixersResources.resx
index 984a7d634dec9..e3244f07eb3af 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
-
- Overload operator equals on overriding ValueType.Equals
-
Seal attribute type.
diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
index 0fa6f3587b498..31a632f78977e 100644
--- a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
+++ b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
@@ -102,11 +102,9 @@
-
-
@@ -156,10 +154,8 @@
-
-
diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs b/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs
index f873ef430bb27..573bd300bc149 100644
--- a/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs
+++ b/src/Diagnostics/FxCop/Core/FxCopRulesResources.Designer.cs
@@ -87,15 +87,6 @@ internal static string AddSerializableAttributeToType {
}
}
- ///
- /// Looks up a localized string similar to Assemblies should be marked with AssemblyVersionAttribute.
- ///
- internal static string AssembliesShouldBeMarkedWithAssemblyVersionAttribute {
- get {
- return ResourceManager.GetString("AssembliesShouldBeMarkedWithAssemblyVersionAttribute", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Avoid unsealed attributes..
///
@@ -105,24 +96,6 @@ internal static string AvoidUnsealedAttributes {
}
}
- ///
- /// Looks up a localized string similar to Consider changing the ComVisible attribute on {0} to false, and opting in at the type level..
- ///
- internal static string CA1017_AttributeTrue {
- get {
- return ResourceManager.GetString("CA1017_AttributeTrue", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Because {0} exposes externally visible types, mark it with ComVisible(false) at the assembly level and then mark all types within the assembly that should be exposed to COM clients with ComVisible(true)..
- ///
- internal static string CA1017_NoAttribute {
- get {
- return ResourceManager.GetString("CA1017_NoAttribute", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Design.
///
@@ -375,24 +348,6 @@ internal static string InterfaceNamesShouldStartWithI {
}
}
- ///
- /// Looks up a localized string similar to Mark all assemblies with ComVisible.
- ///
- internal static string MarkAllAssembliesWithComVisible {
- get {
- return ResourceManager.GetString("MarkAllAssembliesWithComVisible", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The System.Runtime.InteropServices.ComVisible attribute indicates whether COM clients can use the library. Good design dictates that developers explicitly indicate COM visibility. The default value for this attribute is 'true'. However, the best design is to mark the assembly ComVisible false, and then mark types, interfaces, and individual members as ComVisible true, as appropriate..
- ///
- internal static string MarkAllAssembliesWithComVisibleDescription {
- get {
- return ResourceManager.GetString("MarkAllAssembliesWithComVisibleDescription", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Mark all non-serializable fields..
///
@@ -411,24 +366,6 @@ internal static string MarkAllNonSerializableFieldsDescription {
}
}
- ///
- /// Looks up a localized string similar to Mark assemblies with CLSCompliantAttribute.
- ///
- internal static string MarkAssembliesWithCLSCompliantAttribute {
- get {
- return ResourceManager.GetString("MarkAssembliesWithCLSCompliantAttribute", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Assemblies should explicitly state their CLS compliance using the CLSCompliant attribute. An assembly without this attribute is not CLS-compliant. Assemblies, modules, and types can be CLS-compliant even if some parts of the assembly, module, or type are not CLS-compliant. The following rules apply: 1) If the element is marked CLSCompliant, any noncompliant members must have the CLSCompliant attribute present with its argument set to false. 2) A comparable CLS-compliant alternative member must be supplied f [rest of string was truncated]";.
- ///
- internal static string MarkAssembliesWithCLSCompliantDescription {
- get {
- return ResourceManager.GetString("MarkAssembliesWithCLSCompliantDescription", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Mark Enum with FlagsAttribute.
///
@@ -483,24 +420,6 @@ internal static string MovePInvokesToNativeMethodsClass {
}
}
- ///
- /// Looks up a localized string similar to Overload operator equals on overriding ValueType.Equals.
- ///
- internal static string OverloadOperatorEqualsOnOverridingValueTypeEquals {
- get {
- return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEquals", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to 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..
- ///
- internal static string OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription {
- get {
- return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to P/Invoke method '{0}' should not be visible.
///
diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx b/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx
index 3fce0ad6327fa..467e49a6fc17c 100644
--- a/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx
+++ b/src/Diagnostics/FxCop/Core/FxCopRulesResources.resx
@@ -120,9 +120,6 @@
Type '{0}' owns disposable fields but is not disposable
-
- Overload operator equals on overriding ValueType.Equals
-
Type '{0}' is abstract but has public constructors
@@ -156,12 +153,6 @@
Declare serialization constructor for unsealed type {0} as protected
-
- Assemblies should be marked with AssemblyVersionAttribute
-
-
- Mark assemblies with CLSCompliantAttribute
-
Disposable fields should be disposed
@@ -234,18 +225,9 @@
Change the accessibility of all public contructors in this class to protected.
-
- Because {0} exposes externally visible types, mark it with ComVisible(false) at the assembly level and then mark all types within the assembly that should be exposed to COM clients with ComVisible(true).
-
-
- Consider changing the ComVisible attribute on {0} to false, and opting in at the type level.
-
Identifier names should differ by more than case
-
- Mark all assemblies with ComVisible
-
Abstract classes should not have public constructors
@@ -276,9 +258,6 @@
An enum should generally have a zero value. If the enum is not decorated with the Flags attribute, it should have a member with a value of zero that represents the empty state. Optionally, this value is named 'None'. For a Flags-attributed enum, a zero-valued member is optional and, if it exists, should always be named 'None'. This value should indicate that no values have been set in the enum. Using a zero-valued member for other purposes is contrary to the use of the Flags attribute in that the bitwise AND and OR operators are useless with the member.
-
- The System.Runtime.InteropServices.ComVisible attribute indicates whether COM clients can use the library. Good design dictates that developers explicitly indicate COM visibility. The default value for this attribute is 'true'. However, the best design is to mark the assembly ComVisible false, and then mark types, interfaces, and individual members as ComVisible true, as appropriate.
-
Properties should be used instead of Get/Set methods in most situations. Methods are preferable to properties in the following situations: the operation is a conversion, is expensive or has an observable side-effect; the order of execution is important; calling the member twice in succession creates different results; a member is static but returns a mutable value; or the member returns an array.
@@ -297,18 +276,12 @@
All fields that cannot be serialized directly should have the NonSerializedAttribute. Types that have the SerializableAttribute should not have fields of types that do not have the SerializableAttribute unless the fields are marked with the NonSerializedAttribute.
-
- Assemblies should explicitly state their CLS compliance using the CLSCompliant attribute. An assembly without this attribute is not CLS-compliant. Assemblies, modules, and types can be CLS-compliant even if some parts of the assembly, module, or type are not CLS-compliant. The following rules apply: 1) If the element is marked CLSCompliant, any noncompliant members must have the CLSCompliant attribute present with its argument set to false. 2) A comparable CLS-compliant alternative member must be supplied for each member that is not CLS-compliant.
-
The enumeration appears to be made up of combinable flags. If this true, apply the Flags attribute to the enumeration.
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.
-
- 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.
-
Finalizers should be avoided where possible, to avoid the additional performance overhead involved in tracking object lifetime.
diff --git a/src/Diagnostics/FxCop/Core/Usage/CA2231DiagnosticAnalyzer.cs b/src/Diagnostics/FxCop/Core/Usage/CA2231DiagnosticAnalyzer.cs
deleted file mode 100644
index d4c4398271e13..0000000000000
--- a/src/Diagnostics/FxCop/Core/Usage/CA2231DiagnosticAnalyzer.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-// 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.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
-
-namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
-{
- ///
- /// CA2231: Complain if the type implements Equals without overloading the equality operator.
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
- public sealed class CA2231DiagnosticAnalyzer : AbstractNamedTypeAnalyzer
- {
- internal const string RuleId = "CA2231";
- private static LocalizableString s_localizableMessageAndTitle = new LocalizableResourceString(nameof(FxCopRulesResources.OverloadOperatorEqualsOnOverridingValueTypeEquals), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
- private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(FxCopRulesResources.OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
-
- internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
- s_localizableMessageAndTitle,
- s_localizableMessageAndTitle,
- FxCopDiagnosticCategory.Usage,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: s_localizableDescription,
- helpLinkUri: "http://msdn.microsoft.com/library/ms182359.aspx",
- customTags: DiagnosticCustomTags.Microsoft);
-
- public override ImmutableArray SupportedDiagnostics
- {
- get
- {
- return ImmutableArray.Create(Rule);
- }
- }
-
- protected override void AnalyzeSymbol(INamedTypeSymbol namedTypeSymbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken)
- {
- if (namedTypeSymbol.IsValueType && IsOverridesEquals(namedTypeSymbol) && !IsEqualityOperatorImplemented(namedTypeSymbol))
- {
- addDiagnostic(namedTypeSymbol.CreateDiagnostic(Rule));
- }
- }
-
- private static bool IsOverridesEquals(INamedTypeSymbol symbol)
- {
- // do override Object.Equals?
- return symbol.GetMembers(WellKnownMemberNames.ObjectEquals).OfType().Where(m => IsEqualsOverride(m)).Any();
- }
-
- private static bool IsEqualsOverride(IMethodSymbol method)
- {
- return method != null &&
- method.IsOverride &&
- method.ReturnType.SpecialType == SpecialType.System_Boolean &&
- method.Parameters.Length == 1 &&
- method.Parameters[0].Type.SpecialType == SpecialType.System_Object;
- }
-
- private static bool IsEqualityOperatorImplemented(INamedTypeSymbol symbol)
- {
- // do implement the equality operator?
- return symbol.GetMembers(WellKnownMemberNames.EqualityOperatorName).OfType().Where(m => m.MethodKind == MethodKind.UserDefinedOperator).Any() ||
- symbol.GetMembers(WellKnownMemberNames.InequalityOperatorName).OfType().Where(m => m.MethodKind == MethodKind.UserDefinedOperator).Any();
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/Core/Usage/CodeFixes/CA2231CodeFixProviderBase.cs b/src/Diagnostics/FxCop/Core/Usage/CodeFixes/CA2231CodeFixProviderBase.cs
deleted file mode 100644
index 84e6e08a4a13e..0000000000000
--- a/src/Diagnostics/FxCop/Core/Usage/CodeFixes/CA2231CodeFixProviderBase.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.Collections.Immutable;
-
-namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
-{
- ///
- /// CA2231: Overload operator equals on overriding ValueType.Equals
- ///
- public abstract class CA2231CodeFixProviderBase : CodeFixProviderBase
- {
- protected const string LeftName = "left";
- protected const string RightName = "right";
- protected const string NotImplementedExceptionName = "System.NotImplementedException";
-
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(CA2231DiagnosticAnalyzer.RuleId); }
- }
-
- protected sealed override string GetCodeFixDescription(Diagnostic diagnostic)
- {
- return FxCopFixersResources.OverloadOperatorEqualsOnOverridingValueTypeEquals;
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj
index d838fc4d6d9f8..9d2a8ffce7025 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj
@@ -73,6 +73,7 @@
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
new file mode 100644
index 0000000000000..9a4e57495674e
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
@@ -0,0 +1,54 @@
+// 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.Collections.Generic;
+using System.Composition;
+using System.Diagnostics;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace System.Runtime.Analyzers
+{
+ ///
+ /// CA2231: Overload operator equals on overriding ValueType.Equals
+ ///
+ [ExportCodeFixProvider(LanguageNames.CSharp), Shared]
+ public class CSharpOverloadOperatorEqualsOnOverridingValueTypeEqualsFixer : OverloadOperatorEqualsOnOverridingValueTypeEqualsFixer
+ {
+ protected override SyntaxNode GenerateOperatorDeclaration(SyntaxNode returnType, string operatorName, IEnumerable parameters, SyntaxNode notImplementedStatement)
+ {
+ Debug.Assert(returnType is TypeSyntax);
+
+ SyntaxToken operatorToken;
+ switch (operatorName)
+ {
+ case WellKnownMemberNames.EqualityOperatorName:
+ operatorToken = SyntaxFactory.Token(SyntaxKind.EqualsEqualsToken);
+ break;
+ case WellKnownMemberNames.InequalityOperatorName:
+ operatorToken = SyntaxFactory.Token(SyntaxKind.ExclamationEqualsToken);
+ break;
+ case WellKnownMemberNames.LessThanOperatorName:
+ operatorToken = SyntaxFactory.Token(SyntaxKind.LessThanToken);
+ break;
+ case WellKnownMemberNames.GreaterThanOperatorName:
+ operatorToken = SyntaxFactory.Token(SyntaxKind.GreaterThanToken);
+ break;
+ default:
+ return null;
+ }
+
+ return SyntaxFactory.OperatorDeclaration(
+ default(SyntaxList),
+ SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword) }),
+ (TypeSyntax)returnType,
+ SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
+ operatorToken,
+ SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters.Cast())),
+ SyntaxFactory.Block((StatementSyntax)notImplementedStatement),
+ default(SyntaxToken));
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs
similarity index 78%
rename from src/Diagnostics/FxCop/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs
index 7e587d1f3135d..7ded8b4658856 100644
--- a/src/Diagnostics/FxCop/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/AssemblyAttributesDiagnosticAnalyzer.cs
@@ -1,48 +1,40 @@
// 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.Collections.Immutable;
+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 AssemblyAttributesDiagnosticAnalyzer : DiagnosticAnalyzer
{
- internal const string CA1016RuleName = "CA1016";
- internal const string CA1014RuleName = "CA1014";
+ internal const string CA1016RuleId = "CA1016";
+ internal const string CA1014RuleId = "CA1014";
- private static LocalizableString s_localizableMessageCA1016 = new LocalizableResourceString(nameof(FxCopRulesResources.AssembliesShouldBeMarkedWithAssemblyVersionAttribute), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
- internal static DiagnosticDescriptor CA1016Rule = new DiagnosticDescriptor(CA1016RuleName,
+ private static LocalizableString s_localizableMessageCA1016 = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.AssembliesShouldBeMarkedWithAssemblyVersionAttribute), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+ internal static DiagnosticDescriptor CA1016Rule = new DiagnosticDescriptor(CA1016RuleId,
s_localizableMessageCA1016,
s_localizableMessageCA1016,
- FxCopDiagnosticCategory.Design,
+ DiagnosticCategory.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: "http://msdn.microsoft.com/library/ms182155.aspx",
- customTags: DiagnosticCustomTags.Microsoft);
+ customTags: WellKnownDiagnosticTags.Telemetry);
- private static LocalizableString s_localizableMessageCA1014 = new LocalizableResourceString(nameof(FxCopRulesResources.MarkAssembliesWithCLSCompliantAttribute), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
- private static LocalizableString s_localizableDescriptionCA1014 = new LocalizableResourceString(nameof(FxCopRulesResources.MarkAssembliesWithCLSCompliantDescription), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
- internal static DiagnosticDescriptor CA1014Rule = new DiagnosticDescriptor(CA1014RuleName,
+ private static LocalizableString s_localizableMessageCA1014 = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.MarkAssembliesWithCLSCompliantAttribute), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+ private static LocalizableString s_localizableDescriptionCA1014 = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.MarkAssembliesWithCLSCompliantDescription), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+ internal static DiagnosticDescriptor CA1014Rule = new DiagnosticDescriptor(CA1014RuleId,
s_localizableMessageCA1014,
s_localizableMessageCA1014,
- FxCopDiagnosticCategory.Design,
+ DiagnosticCategory.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: false,
description: s_localizableDescriptionCA1014,
helpLinkUri: "http://msdn.microsoft.com/library/ms182156.aspx",
- customTags: DiagnosticCustomTags.Microsoft);
-
- private static readonly ImmutableArray s_supportedDiagnostics = ImmutableArray.Create(CA1016Rule, CA1014Rule);
-
- public override ImmutableArray SupportedDiagnostics
- {
- get
- {
- return s_supportedDiagnostics;
- }
- }
+ customTags: WellKnownDiagnosticTags.Telemetry);
+
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(CA1016Rule, CA1014Rule);
public override void Initialize(AnalysisContext analysisContext)
{
diff --git a/src/Diagnostics/FxCop/Core/Design/CA1017DiagnosticAnalyzer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAllAssembliesWithComVisible.cs
similarity index 79%
rename from src/Diagnostics/FxCop/Core/Design/CA1017DiagnosticAnalyzer.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAllAssembliesWithComVisible.cs
index 7dacacac8910c..f2c10649dcd80 100644
--- a/src/Diagnostics/FxCop/Core/Design/CA1017DiagnosticAnalyzer.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/MarkAllAssembliesWithComVisible.cs
@@ -2,27 +2,27 @@
using System.Collections.Immutable;
using System.Linq;
+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 CA1017DiagnosticAnalyzer : DiagnosticAnalyzer
+ public sealed class MarkAllAssembliesWithComVisibleAnalyzer : DiagnosticAnalyzer
{
internal const string RuleId = "CA1017";
- private static LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(FxCopRulesResources.MarkAllAssembliesWithComVisible), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
- private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(FxCopRulesResources.MarkAllAssembliesWithComVisibleDescription), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
+ private static LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.MarkAllAssembliesWithComVisible), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+ private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.MarkAllAssembliesWithComVisibleDescription), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
s_localizableTitle,
"{0}",
- FxCopDiagnosticCategory.Design,
+ DiagnosticCategory.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: false,
description: s_localizableDescription,
helpLinkUri: "http://msdn.microsoft.com/library/ms182157.aspx",
- customTags: DiagnosticCustomTags.Microsoft);
+ customTags: WellKnownDiagnosticTags.Telemetry);
public override ImmutableArray SupportedDiagnostics
{
@@ -57,13 +57,13 @@ private void AnalyzeCompilation(CompilationEndAnalysisContext context)
attributeInstance.ConstructorArguments[0].Value.Equals(true))
{
// Has the attribute, with the value 'true'.
- context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, string.Format(FxCopRulesResources.CA1017_AttributeTrue, context.Compilation.Assembly.Name)));
+ context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, string.Format(SystemRuntimeAnalyzersResources.CA1017_AttributeTrue, context.Compilation.Assembly.Name)));
}
}
else
{
// No ComVisible attribute at all.
- context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, string.Format(FxCopRulesResources.CA1017_NoAttribute, context.Compilation.Assembly.Name)));
+ context.ReportDiagnostic(Diagnostic.Create(Rule, Location.None, string.Format(SystemRuntimeAnalyzersResources.CA1017_NoAttribute, context.Compilation.Assembly.Name)));
}
}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.Fixer.cs
index 42aade7bf84a8..c88697b4e5595 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.Fixer.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.Fixer.cs
@@ -51,7 +51,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var generator = editor.Generator;
- if (!OverrideMethodsOnComparableTypesAnalyzer.DoesOverrideEquals(typeSymbol))
+ if (!typeSymbol.DoesOverrideEquals())
{
var equalsMethod = generator.MethodDeclaration(WellKnownMemberNames.ObjectEquals,
new[] { generator.ParameterDeclaration("obj", generator.TypeExpression(SpecialType.System_Object)) },
@@ -62,7 +62,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
editor.AddMember(declaration, equalsMethod);
}
- if (!OverrideMethodsOnComparableTypesAnalyzer.DoesOverrideGetHashCode(typeSymbol))
+ if (!typeSymbol.DoesOverrideGetHashCode())
{
var getHashCodeMethod = generator.MethodDeclaration(WellKnownMemberNames.ObjectGetHashCode,
returnType: generator.TypeExpression(SpecialType.System_Int32),
@@ -72,7 +72,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
editor.AddMember(declaration, getHashCodeMethod);
}
- if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.EqualityOperatorName))
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.EqualityOperatorName))
{
var equalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
WellKnownMemberNames.EqualityOperatorName,
@@ -85,7 +85,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
editor.AddMember(declaration, equalityOperator);
}
- if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.InequalityOperatorName))
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.InequalityOperatorName))
{
var inequalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
WellKnownMemberNames.InequalityOperatorName,
@@ -98,7 +98,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
editor.AddMember(declaration, inequalityOperator);
}
- if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.LessThanOperatorName))
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.LessThanOperatorName))
{
var lessThanOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
WellKnownMemberNames.LessThanOperatorName,
@@ -111,7 +111,7 @@ private async Task ImplementComparable(Document document, SyntaxNode d
editor.AddMember(declaration, lessThanOperator);
}
- if (!OverrideMethodsOnComparableTypesAnalyzer.IsOperatorImplemented(typeSymbol, WellKnownMemberNames.GreaterThanOperatorName))
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.GreaterThanOperatorName))
{
var greaterThanOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
WellKnownMemberNames.GreaterThanOperatorName,
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs
index 5dd70dd7db522..5897ce3c622ab 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/OverrideMethodsOnComparableTypes.cs
@@ -64,53 +64,21 @@ private static void AnalyzeSymbol(INamedTypeSymbol namedTypeSymbol, INamedTypeSy
if (namedTypeSymbol.AllInterfaces.Any(t => t.Equals(comparableType) ||
(t.ConstructedFrom?.Equals(genericComparableType) ?? false)))
{
- if (!(DoesOverrideEquals(namedTypeSymbol) && IsEqualityOperatorImplemented(namedTypeSymbol)))
+ if (!(namedTypeSymbol.DoesOverrideEquals() && IsEqualityOperatorImplemented(namedTypeSymbol)))
{
addDiagnostic(namedTypeSymbol.CreateDiagnostic(Rule));
}
}
}
- internal static bool DoesOverrideEquals(INamedTypeSymbol symbol)
- {
- // Does the symbol override Object.Equals?
- return symbol.GetMembers(WellKnownMemberNames.ObjectEquals).OfType().Where(m => IsEqualsOverride(m)).Any();
- }
-
- private static bool IsEqualsOverride(IMethodSymbol method)
- {
- return method.IsOverride &&
- method.ReturnType.SpecialType == SpecialType.System_Boolean &&
- method.Parameters.Length == 1 &&
- method.Parameters[0].Type.SpecialType == SpecialType.System_Object;
- }
-
- internal static bool DoesOverrideGetHashCode(INamedTypeSymbol symbol)
- {
- // Does the symbol override Object.GetHashCode?
- return symbol.GetMembers(WellKnownMemberNames.ObjectGetHashCode).OfType().Where(m => IsGetHashCodeOverride(m)).Any();
- }
-
- private static bool IsGetHashCodeOverride(IMethodSymbol method)
- {
- return method.IsOverride &&
- method.ReturnType.SpecialType == SpecialType.System_Int32 &&
- method.Parameters.Length == 0;
- }
-
private static bool IsEqualityOperatorImplemented(INamedTypeSymbol symbol)
{
// Does the symbol overload all of the equality operators? (All are required per http://msdn.microsoft.com/en-us/library/ms182163.aspx example.)
- return IsOperatorImplemented(symbol, WellKnownMemberNames.EqualityOperatorName) &&
- IsOperatorImplemented(symbol, WellKnownMemberNames.InequalityOperatorName) &&
- IsOperatorImplemented(symbol, WellKnownMemberNames.LessThanOperatorName) &&
- IsOperatorImplemented(symbol, WellKnownMemberNames.GreaterThanOperatorName);
+ return symbol.IsOperatorImplemented(WellKnownMemberNames.EqualityOperatorName) &&
+ symbol.IsOperatorImplemented(WellKnownMemberNames.InequalityOperatorName) &&
+ symbol.IsOperatorImplemented(WellKnownMemberNames.LessThanOperatorName) &&
+ symbol.IsOperatorImplemented(WellKnownMemberNames.GreaterThanOperatorName);
}
- internal static bool IsOperatorImplemented(INamedTypeSymbol symbol, string op)
- {
- // TODO: should this filter on the right-hand-side operator type?
- return symbol.GetMembers(op).OfType().Where(m => m.MethodKind == MethodKind.UserDefinedOperator).Any();
- }
}
}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Extensions/INamedTypeSymbolExtensions.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Extensions/INamedTypeSymbolExtensions.cs
deleted file mode 100644
index cc7f1ad773676..0000000000000
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Extensions/INamedTypeSymbolExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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.Collections.Generic;
-using Microsoft.CodeAnalysis;
-
-namespace System.Runtime.Analyzers
-{
- internal static class INamedTypeSymbolExtensions
- {
- public static IEnumerable GetBaseTypesAndThis(this INamedTypeSymbol type)
- {
- var current = type;
- while (current != null)
- {
- yield return current;
- current = current.BaseType;
- }
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Extensions/DiagnosticExtensions.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Shared/DiagnosticExtensions.cs
similarity index 100%
rename from src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Extensions/DiagnosticExtensions.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Shared/DiagnosticExtensions.cs
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Shared/INamedTypeSymbolExtensions.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Shared/INamedTypeSymbolExtensions.cs
new file mode 100644
index 0000000000000..db0b35616f729
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Shared/INamedTypeSymbolExtensions.cs
@@ -0,0 +1,54 @@
+// 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.Collections.Generic;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+
+namespace System.Runtime.Analyzers
+{
+ internal static class INamedTypeSymbolExtensions
+ {
+ public static IEnumerable GetBaseTypesAndThis(this INamedTypeSymbol type)
+ {
+ var current = type;
+ while (current != null)
+ {
+ yield return current;
+ current = current.BaseType;
+ }
+ }
+
+ public static bool IsOperatorImplemented(this INamedTypeSymbol symbol, string op)
+ {
+ // TODO: should this filter on the right-hand-side operator type?
+ return symbol.GetMembers(op).OfType().Where(m => m.MethodKind == MethodKind.UserDefinedOperator).Any();
+ }
+
+ public static bool DoesOverrideEquals(this INamedTypeSymbol symbol)
+ {
+ // Does the symbol override Object.Equals?
+ return symbol.GetMembers(WellKnownMemberNames.ObjectEquals).OfType().Where(m => IsEqualsOverride(m)).Any();
+ }
+
+ private static bool IsEqualsOverride(IMethodSymbol method)
+ {
+ return method.IsOverride &&
+ method.ReturnType.SpecialType == SpecialType.System_Boolean &&
+ method.Parameters.Length == 1 &&
+ method.Parameters[0].Type.SpecialType == SpecialType.System_Object;
+ }
+
+ public static bool DoesOverrideGetHashCode(this INamedTypeSymbol symbol)
+ {
+ // Does the symbol override Object.GetHashCode?
+ return symbol.GetMembers(WellKnownMemberNames.ObjectGetHashCode).OfType().Where(m => IsGetHashCodeOverride(m)).Any();
+ }
+
+ private static bool IsGetHashCodeOverride(IMethodSymbol method)
+ {
+ return method.IsOverride &&
+ method.ReturnType.SpecialType == SpecialType.System_Int32 &&
+ method.Parameters.Length == 0;
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj
index 5ecf6945d62ce..660f28b115c7d 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj
@@ -53,6 +53,8 @@
+
+
@@ -61,15 +63,17 @@
-
+
-
+
True
True
SystemRuntimeAnalyzersResources.resx
+
+
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 420000e1c4167..cc9142e80e22b 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs
@@ -61,6 +61,33 @@ internal SystemRuntimeAnalyzersResources() {
}
}
+ ///
+ /// Looks up a localized string similar to Assemblies should be marked with AssemblyVersionAttribute.
+ ///
+ internal static string AssembliesShouldBeMarkedWithAssemblyVersionAttribute {
+ get {
+ return ResourceManager.GetString("AssembliesShouldBeMarkedWithAssemblyVersionAttribute", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Consider changing the ComVisible attribute on {0} to false, and opting in at the type level..
+ ///
+ internal static string CA1017_AttributeTrue {
+ get {
+ return ResourceManager.GetString("CA1017_AttributeTrue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Because {0} exposes externally visible types, mark it with ComVisible(false) at the assembly level and then mark all types within the assembly that should be exposed to COM clients with ComVisible(true)..
+ ///
+ internal static string CA1017_NoAttribute {
+ get {
+ return ResourceManager.GetString("CA1017_NoAttribute", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Design.
///
@@ -214,6 +241,42 @@ internal static string MakeSetterNonPublic {
}
}
+ ///
+ /// Looks up a localized string similar to Mark all assemblies with ComVisible.
+ ///
+ internal static string MarkAllAssembliesWithComVisible {
+ get {
+ return ResourceManager.GetString("MarkAllAssembliesWithComVisible", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The System.Runtime.InteropServices.ComVisible attribute indicates whether COM clients can use the library. Good design dictates that developers explicitly indicate COM visibility. The default value for this attribute is 'true'. However, the best design is to mark the assembly ComVisible false, and then mark types, interfaces, and individual members as ComVisible true, as appropriate..
+ ///
+ internal static string MarkAllAssembliesWithComVisibleDescription {
+ get {
+ return ResourceManager.GetString("MarkAllAssembliesWithComVisibleDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Mark assemblies with CLSCompliantAttribute.
+ ///
+ internal static string MarkAssembliesWithCLSCompliantAttribute {
+ get {
+ return ResourceManager.GetString("MarkAssembliesWithCLSCompliantAttribute", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Assemblies should explicitly state their CLS compliance using the CLSCompliant attribute. An assembly without this attribute is not CLS-compliant. Assemblies, modules, and types can be CLS-compliant even if some parts of the assembly, module, or type are not CLS-compliant. The following rules apply: 1) If the element is marked CLSCompliant, any noncompliant members must have the CLSCompliant attribute present with its argument set to false. 2) A comparable CLS-compliant alternative member must be supplied f [rest of string was truncated]";.
+ ///
+ internal static string MarkAssembliesWithCLSCompliantDescription {
+ get {
+ return ResourceManager.GetString("MarkAssembliesWithCLSCompliantDescription", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Specify AttributeUsage attribute on '{0}' attribute class..
///
@@ -241,6 +304,33 @@ internal static string OverloadOperatorEqualsOnIComparableInterfaceDescription {
}
}
+ ///
+ /// Looks up a localized string similar to Overload operator equals on overriding ValueType.Equals.
+ ///
+ internal static string OverloadOperatorEqualsOnOverridingValueTypeEquals {
+ get {
+ return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEquals", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Overload operator equals on overriding ValueType.Equals.
+ ///
+ internal static string OverloadOperatorEqualsOnOverridingValueTypeEquals1 {
+ get {
+ return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEquals1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 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..
+ ///
+ internal static string OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription {
+ get {
+ return ResourceManager.GetString("OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription", 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 9649a0feecc9b..7f4e87bb1878f 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx
@@ -183,4 +183,34 @@
Make the setter of the property non-public
+
+ Overload operator equals on overriding ValueType.Equals
+
+
+ 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.
+
+
+ Overload operator equals on overriding ValueType.Equals
+
+
+ Mark assemblies with CLSCompliantAttribute
+
+
+ Assemblies should explicitly state their CLS compliance using the CLSCompliant attribute. An assembly without this attribute is not CLS-compliant. Assemblies, modules, and types can be CLS-compliant even if some parts of the assembly, module, or type are not CLS-compliant. The following rules apply: 1) If the element is marked CLSCompliant, any noncompliant members must have the CLSCompliant attribute present with its argument set to false. 2) A comparable CLS-compliant alternative member must be supplied for each member that is not CLS-compliant.
+
+
+ Assemblies should be marked with AssemblyVersionAttribute
+
+
+ Mark all assemblies with ComVisible
+
+
+ The System.Runtime.InteropServices.ComVisible attribute indicates whether COM clients can use the library. Good design dictates that developers explicitly indicate COM visibility. The default value for this attribute is 'true'. However, the best design is to mark the assembly ComVisible false, and then mark types, interfaces, and individual members as ComVisible true, as appropriate.
+
+
+ Consider changing the ComVisible attribute on {0} to false, and opting in at the type level.
+
+
+ Because {0} exposes externally visible types, mark it with ComVisible(false) at the assembly level and then mark all types within the assembly that should be exposed to COM clients with ComVisible(true).
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
new file mode 100644
index 0000000000000..2fd2a0e4152f9
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
@@ -0,0 +1,97 @@
+// 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.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Editing;
+
+namespace System.Runtime.Analyzers
+{
+ ///
+ /// CA2231: Overload operator equals on overriding ValueType.Equals
+ ///
+ public abstract class OverloadOperatorEqualsOnOverridingValueTypeEqualsFixer : CodeFixProvider
+ {
+ protected const string LeftName = "left";
+ protected const string RightName = "right";
+ protected const string NotImplementedExceptionName = "System.NotImplementedException";
+
+ public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer.RuleId);
+
+ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ var generator = SyntaxGenerator.GetGenerator(context.Document);
+ var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
+
+ var declaration = root.FindNode(context.Span);
+ declaration = generator.GetDeclaration(declaration);
+ if (declaration == null)
+ {
+ return;
+ }
+
+ var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
+ var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
+ if (typeSymbol == null)
+ {
+ return;
+ }
+
+ // We cannot have multiple overlapping diagnostics of this id.
+ var diagnostic = context.Diagnostics.Single();
+
+ context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnOverridingValueTypeEquals,
+ async ct => await ImplementOperatorEquals(context.Document, declaration, typeSymbol, ct).ConfigureAwait(false)),
+ diagnostic);
+ }
+
+ protected abstract SyntaxNode GenerateOperatorDeclaration(SyntaxNode returnType, string operatorName, IEnumerable parameters, SyntaxNode notImplementedStatement);
+
+ private async Task ImplementOperatorEquals(Document document, SyntaxNode declaration, INamedTypeSymbol typeSymbol, CancellationToken cancellationToken)
+ {
+ DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
+ var generator = editor.Generator;
+
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.EqualityOperatorName))
+ {
+ var equalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
+ WellKnownMemberNames.EqualityOperatorName,
+ new[]
+ {
+ generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)),
+ generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)),
+ },
+ generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException"))));
+ editor.AddMember(declaration, equalityOperator);
+ }
+
+ if (!typeSymbol.IsOperatorImplemented(WellKnownMemberNames.InequalityOperatorName))
+ {
+ var inequalityOperator = GenerateOperatorDeclaration(generator.TypeExpression(SpecialType.System_Boolean),
+ WellKnownMemberNames.InequalityOperatorName,
+ new[]
+ {
+ generator.ParameterDeclaration("left", generator.TypeExpression(typeSymbol)),
+ generator.ParameterDeclaration("right", generator.TypeExpression(typeSymbol)),
+ },
+ generator.ThrowStatement(generator.ObjectCreationExpression(generator.DottedName("System.NotImplementedException"))));
+ editor.AddMember(declaration, inequalityOperator);
+ }
+
+ return editor.GetChangedDocument();
+
+ }
+
+ private class MyCodeAction : DocumentChangeAction
+ {
+ public MyCodeAction(string title, Func> createChangedDocument)
+ : base(title, createChangedDocument)
+ {
+ }
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs
new file mode 100644
index 0000000000000..2ec0152927c5b
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs
@@ -0,0 +1,56 @@
+// 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.Collections.Immutable;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace System.Runtime.Analyzers
+{
+ ///
+ /// CA2231: Complain if the type implements Equals without overloading the equality operator.
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
+ public sealed class OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer : DiagnosticAnalyzer
+ {
+ internal const string RuleId = "CA2231";
+ private static LocalizableString s_localizableMessageAndTitle = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnOverridingValueTypeEquals), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+ private static LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnOverridingValueTypeEqualsDescription), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources));
+
+ internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
+ s_localizableMessageAndTitle,
+ s_localizableMessageAndTitle,
+ DiagnosticCategory.Usage,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true,
+ description: s_localizableDescription,
+ helpLinkUri: "http://msdn.microsoft.com/library/ms182359.aspx",
+ customTags: WellKnownDiagnosticTags.Telemetry);
+
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
+
+ public override void Initialize(AnalysisContext analysisContext)
+ {
+ analysisContext.RegisterSymbolAction(context =>
+ {
+ AnalyzeSymbol((INamedTypeSymbol)context.Symbol, context.ReportDiagnostic);
+ },
+ SymbolKind.NamedType);
+ }
+
+ private static void AnalyzeSymbol(INamedTypeSymbol namedTypeSymbol, Action addDiagnostic)
+ {
+ if (namedTypeSymbol.IsValueType && namedTypeSymbol.DoesOverrideEquals() && !IsEqualityOperatorImplemented(namedTypeSymbol))
+ {
+ addDiagnostic(namedTypeSymbol.CreateDiagnostic(Rule));
+ }
+ }
+
+ private static bool IsEqualityOperatorImplemented(INamedTypeSymbol symbol)
+ {
+ return symbol.IsOperatorImplemented(WellKnownMemberNames.EqualityOperatorName) ||
+ symbol.IsOperatorImplemented(WellKnownMemberNames.InequalityOperatorName);
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/Test/Design/CA1017Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAllAssembliesWithComVisibleTests.cs
similarity index 81%
rename from src/Diagnostics/FxCop/Test/Design/CA1017Tests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAllAssembliesWithComVisibleTests.cs
index 63f73c06f454d..9cbe06df1bdee 100644
--- a/src/Diagnostics/FxCop/Test/Design/CA1017Tests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAllAssembliesWithComVisibleTests.cs
@@ -1,23 +1,22 @@
// 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;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
- public class CA1017Tests : DiagnosticAnalyzerTestBase
+ public class MarkAllAssembliesWithComVisibleTests : DiagnosticAnalyzerTestBase
{
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
- return new CA1017DiagnosticAnalyzer();
+ return new MarkAllAssembliesWithComVisibleAnalyzer();
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
- return new CA1017DiagnosticAnalyzer();
+ return new MarkAllAssembliesWithComVisibleAnalyzer();
}
[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
@@ -118,12 +117,12 @@ internal class C
private static DiagnosticResult GetExposeIndividualTypesResult()
{
- return GetGlobalResult(CA1017DiagnosticAnalyzer.RuleId, string.Format(FxCopRulesResources.CA1017_AttributeTrue, "TestProject"));
+ return GetGlobalResult(MarkAllAssembliesWithComVisibleAnalyzer.RuleId, string.Format(SystemRuntimeAnalyzersResources.CA1017_AttributeTrue, "TestProject"));
}
private static DiagnosticResult GetAddComVisibleFalseResult()
{
- return GetGlobalResult(CA1017DiagnosticAnalyzer.RuleId, string.Format(FxCopRulesResources.CA1017_NoAttribute, "TestProject"));
+ return GetGlobalResult(MarkAllAssembliesWithComVisibleAnalyzer.RuleId, string.Format(SystemRuntimeAnalyzersResources.CA1017_NoAttribute, "TestProject"));
}
}
}
diff --git a/src/Diagnostics/FxCop/Test/Design/CA1016Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithAssemblyVersionAttributeTests.cs
similarity index 94%
rename from src/Diagnostics/FxCop/Test/Design/CA1016Tests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithAssemblyVersionAttributeTests.cs
index 946d40314f708..0ce4b3d85b8e5 100644
--- a/src/Diagnostics/FxCop/Test/Design/CA1016Tests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithAssemblyVersionAttributeTests.cs
@@ -1,13 +1,14 @@
// 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;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
- public class CA1016Tests : DiagnosticAnalyzerTestBase
+ public class MarkAssembliesWithAssemblyVersionAttributeTests : DiagnosticAnalyzerTestBase
{
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
diff --git a/src/Diagnostics/FxCop/Test/Design/CA1014Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithCLSCompliantAttributeTests.cs
similarity index 95%
rename from src/Diagnostics/FxCop/Test/Design/CA1014Tests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithCLSCompliantAttributeTests.cs
index bb83d36306710..c191a3fc96912 100644
--- a/src/Diagnostics/FxCop/Test/Design/CA1014Tests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Design/MarkAssembliesWithCLSCompliantAttributeTests.cs
@@ -1,13 +1,14 @@
// 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;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
- public class CA1014Tests : DiagnosticAnalyzerTestBase
+ public class MarkAssembliesWithCLSCompliantAttributeTests : DiagnosticAnalyzerTestBase
{
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
@@ -189,14 +190,14 @@ static void Main(string[] args)
private static DiagnosticResult s_diagnosticCA1014 = new DiagnosticResult
{
- Id = AssemblyAttributesDiagnosticAnalyzer.CA1014RuleName,
+ Id = AssemblyAttributesDiagnosticAnalyzer.CA1014RuleId,
Severity = DiagnosticSeverity.Warning,
Message = AssemblyAttributesDiagnosticAnalyzer.CA1014Rule.MessageFormat.ToString()
};
private static DiagnosticResult s_diagnosticCA1016 = new DiagnosticResult
{
- Id = AssemblyAttributesDiagnosticAnalyzer.CA1016RuleName,
+ Id = AssemblyAttributesDiagnosticAnalyzer.CA1016RuleId,
Severity = DiagnosticSeverity.Warning,
Message = AssemblyAttributesDiagnosticAnalyzer.CA1016Rule.MessageFormat.ToString()
};
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj
index 47e1902627734..3e21a75706d35 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj
@@ -97,6 +97,9 @@
+
+
+
@@ -104,6 +107,8 @@
+
+
diff --git a/src/Diagnostics/FxCop/Test/Usage/CodeFixes/CA2231FixerTests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
similarity index 75%
rename from src/Diagnostics/FxCop/Test/Usage/CodeFixes/CA2231FixerTests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
index 491ab9360f993..2364541eefbaa 100644
--- a/src/Diagnostics/FxCop/Test/Usage/CodeFixes/CA2231FixerTests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.cs
@@ -1,35 +1,22 @@
// 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.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Usage;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Usage;
using Microsoft.CodeAnalysis.Test.Utilities;
-using Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Usage;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
- public partial class CA2231FixerTests : CodeFixTestBase
+ public partial class OverloadOperatorEqualsOnOverridingValueTypeEqualsTests : CodeFixTestBase
{
- protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
- {
- return new CA2231DiagnosticAnalyzer();
- }
-
protected override CodeFixProvider GetBasicCodeFixProvider()
{
- return new CA2231BasicCodeFixProvider();
- }
-
- protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
- {
- return new CA2231DiagnosticAnalyzer();
+ return new BasicOverloadOperatorEqualsOnOverridingValueTypeEqualsFixer();
}
protected override CodeFixProvider GetCSharpCodeFixProvider()
{
- return new CA2231CSharpCodeFixProvider();
+ return new CSharpOverloadOperatorEqualsOnOverridingValueTypeEqualsFixer();
}
[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
@@ -52,7 +39,7 @@ public override bool Equals(Object obj)
// value type without overridding Equals
public struct A
-{
+{
public override bool Equals(Object obj)
{
return true;
diff --git a/src/Diagnostics/FxCop/Test/Usage/CA2231Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs
similarity index 94%
rename from src/Diagnostics/FxCop/Test/Usage/CA2231Tests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs
index a54bcef99d206..4a42078b6b898 100644
--- a/src/Diagnostics/FxCop/Test/Usage/CA2231Tests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.cs
@@ -1,22 +1,22 @@
// 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.Usage;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
- public partial class CA2231Tests : DiagnosticAnalyzerTestBase
+ public partial class OverloadOperatorEqualsOnOverridingValueTypeEqualsTests : CodeFixTestBase
{
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
- return new CA2231DiagnosticAnalyzer();
+ return new OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer();
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
- return new CA2231DiagnosticAnalyzer();
+ return new OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer();
}
[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj
index 8c60d7075f206..f9fa25519b9c0 100644
--- a/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj
@@ -73,6 +73,7 @@
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.vb b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.vb
new file mode 100644
index 0000000000000..a0b949f3d0987
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/Usage/OverloadOperatorEqualsOnOverridingValueTypeEquals.Fixer.vb
@@ -0,0 +1,42 @@
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports System.Composition
+Imports Microsoft.CodeAnalysis
+Imports Microsoft.CodeAnalysis.CodeFixes
+Imports Microsoft.CodeAnalysis.VisualBasic
+Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
+
+Namespace System.Runtime.Analyzers
+
+ Public Class BasicOverloadOperatorEqualsOnOverridingValueTypeEqualsFixer
+ Inherits OverloadOperatorEqualsOnOverridingValueTypeEqualsFixer
+
+ Protected Overrides Function GenerateOperatorDeclaration(returnType As SyntaxNode, operatorName As String, parameters As IEnumerable(Of SyntaxNode), notImplementedStatement As SyntaxNode) As SyntaxNode
+ Debug.Assert(TypeOf returnType Is TypeSyntax)
+
+ Dim operatorToken As SyntaxToken
+ Select Case operatorName
+ Case WellKnownMemberNames.EqualityOperatorName
+ operatorToken = SyntaxFactory.Token(SyntaxKind.EqualsToken)
+ Case WellKnownMemberNames.InequalityOperatorName
+ operatorToken = SyntaxFactory.Token(SyntaxKind.LessThanGreaterThanToken)
+ Case WellKnownMemberNames.LessThanOperatorName
+ operatorToken = SyntaxFactory.Token(SyntaxKind.LessThanToken)
+ Case WellKnownMemberNames.GreaterThanOperatorName
+ operatorToken = SyntaxFactory.Token(SyntaxKind.GreaterThanToken)
+ Case Else
+ Return Nothing
+ End Select
+
+ Dim operatorStatement = SyntaxFactory.OperatorStatement(Nothing,
+ SyntaxFactory.TokenList(New SyntaxToken() {SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.SharedKeyword)}),
+ SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
+ operatorToken,
+ SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters.Cast(Of ParameterSyntax)())),
+ SyntaxFactory.SimpleAsClause(DirectCast(returnType, TypeSyntax)))
+
+ Return SyntaxFactory.OperatorBlock(operatorStatement,
+ SyntaxFactory.SingletonList(DirectCast(notImplementedStatement, StatementSyntax)))
+ End Function
+ End Class
+End Namespace
diff --git a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
index 0283e115f8050..5188da4cb3214 100644
--- a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
+++ b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
@@ -83,9 +83,6 @@
-
-
-
@@ -110,12 +107,10 @@
-
-
diff --git a/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj b/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
index 06b1019938fe3..bf4437b8987f9 100644
--- a/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
+++ b/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
@@ -111,7 +111,6 @@
-
diff --git a/src/Diagnostics/FxCop/VisualBasic/Usage/CodeFixes/CA2231BasicCodeFixProvider.vb b/src/Diagnostics/FxCop/VisualBasic/Usage/CodeFixes/CA2231BasicCodeFixProvider.vb
deleted file mode 100644
index 595cbf17a6cf7..0000000000000
--- a/src/Diagnostics/FxCop/VisualBasic/Usage/CodeFixes/CA2231BasicCodeFixProvider.vb
+++ /dev/null
@@ -1,80 +0,0 @@
-' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-Imports System.Composition
-Imports System.Threading
-Imports Microsoft.CodeAnalysis
-Imports Microsoft.CodeAnalysis.CodeFixes
-Imports Microsoft.CodeAnalysis.Formatting
-Imports Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
-Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
-
-Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Usage
- '
- ' CA2231: Overload Operator equals on overriding ValueType.Equals
- '
-
- Public Class CA2231BasicCodeFixProvider
- Inherits CA2231CodeFixProviderBase
-
- Friend Overrides Function GetUpdatedDocumentAsync(document As Document, model As SemanticModel, root As SyntaxNode, nodeToFix As SyntaxNode, diagnostic As Diagnostic, cancellationToken As CancellationToken) As Task(Of Document)
- ' We are going to add two operators:
- '
- ' Public Shared Operator =(left As A, right As A) As Boolean
- ' Throw New NotImplementedException()
- ' End Operator
- '
- ' Public Shared Operator <>(left As A, right As A) As Boolean
- ' Throw New NotImplementedException()
- ' End Operator
-
- Dim syntaxNode = TryCast(nodeToFix, StructureStatementSyntax)
- If syntaxNode Is Nothing Then
- Return Task.FromResult(document)
-
- End If
-
- Dim statement = CreateThrowNotImplementedStatement(model)
- If statement Is Nothing Then
- Return Task.FromResult(document)
- End If
-
- Dim params = SyntaxFactory.ParameterList(
- SyntaxFactory.SeparatedList(Of ParameterSyntax)(New ParameterSyntax() {
- SyntaxFactory.Parameter(identifier:=SyntaxFactory.ModifiedIdentifier(LeftName)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(syntaxNode.Identifier.ValueText))),
- SyntaxFactory.Parameter(identifier:=SyntaxFactory.ModifiedIdentifier(RightName)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(syntaxNode.Identifier.ValueText)))
- }))
-
- Dim equalsOperator = CreateOperatorDeclaration(SyntaxKind.EqualsToken, params, statement)
- Dim inequalsOperator = CreateOperatorDeclaration(SyntaxKind.LessThanGreaterThanToken, params, statement)
- Dim parent = DirectCast(syntaxNode.Parent, StructureBlockSyntax)
- Dim newNode = parent.AddMembers(New OperatorBlockSyntax() {equalsOperator, inequalsOperator}).WithAdditionalAnnotations(Formatter.Annotation)
- Return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(parent, newNode)))
- End Function
-
- Protected Function CreateThrowNotImplementedStatement(model As SemanticModel) As StatementSyntax
- Dim exceptionType = model.Compilation.GetTypeByMetadataName(NotImplementedExceptionName)
- If exceptionType Is Nothing Then
- ' If we can't find the exception, we can't generate anything.
- Return Nothing
- End If
-
- Return SyntaxFactory.ThrowStatement(
- SyntaxFactory.ObjectCreationExpression(
- Nothing,
- SyntaxFactory.ParseTypeName(exceptionType.Name),
- SyntaxFactory.ArgumentList(),
- Nothing))
- End Function
-
- Protected Function CreateOperatorDeclaration(kind As SyntaxKind, params As ParameterListSyntax, statement As StatementSyntax) As OperatorBlockSyntax
- Return SyntaxFactory.OperatorBlock(
- SyntaxFactory.OperatorStatement(Nothing,
- SyntaxFactory.TokenList(New SyntaxToken() {SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.SharedKeyword)}),
- SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
- SyntaxFactory.Token(kind),
- params,
- SyntaxFactory.SimpleAsClause(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BooleanKeyword)))),
- SyntaxFactory.SingletonList(statement))
- End Function
- End Class
-End Namespace