diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs
deleted file mode 100644
index da96c09977..0000000000
--- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/CSharpImmutableObjectMethodAnalyzer.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
-
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-using Analyzer.Utilities;
-using Analyzer.Utilities.Extensions;
-using Microsoft.CodeAnalysis.Analyzers;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Diagnostics;
-
-namespace Microsoft.CodeAnalysis.CSharp.Analyzers
-{
- using static CodeAnalysisDiagnosticsResources;
-
- ///
- /// RS1014:
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class CSharpImmutableObjectMethodAnalyzer : DiagnosticAnalyzer
- {
- public static readonly DiagnosticDescriptor DoNotIgnoreReturnValueDiagnosticRule = new(
- DiagnosticIds.DoNotIgnoreReturnValueOnImmutableObjectMethodInvocation,
- CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle)),
- CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationMessage)),
- DiagnosticCategory.MicrosoftCodeAnalysisCorrectness,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationDescription)),
- customTags: WellKnownDiagnosticTagsExtensions.Telemetry);
-
- public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DoNotIgnoreReturnValueDiagnosticRule);
-
- private const string SolutionFullName = @"Microsoft.CodeAnalysis.Solution";
- private const string ProjectFullName = @"Microsoft.CodeAnalysis.Project";
- private const string DocumentFullName = @"Microsoft.CodeAnalysis.Document";
- private const string SyntaxNodeFullName = @"Microsoft.CodeAnalysis.SyntaxNode";
- private const string CompilationFullName = @"Microsoft.CodeAnalysis.Compilation";
-
- private static readonly ImmutableArray s_immutableMethodNames = ImmutableArray.Create(
- "Add",
- "Remove",
- "Replace",
- "With");
-
- public override void Initialize(AnalysisContext context)
- {
- context.EnableConcurrentExecution();
- context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
-
- context.RegisterCompilationStartAction(compilationContext =>
- {
- if (!compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(SolutionFullName, out var solutionSymbol) ||
- !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(ProjectFullName, out var projectSymbol) ||
- !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(DocumentFullName, out var documentSymbol) ||
- !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(SyntaxNodeFullName, out var syntaxNodeSymbol) ||
- !compilationContext.Compilation.TryGetOrCreateTypeByMetadataName(CompilationFullName, out var compilationSymbol))
- {
- // Only register our node action if we can find the symbols for our immutable types
- return;
- }
-
- var immutableSymbols = ImmutableArray.Create(solutionSymbol, projectSymbol, documentSymbol, syntaxNodeSymbol, compilationSymbol);
- compilationContext.RegisterSyntaxNodeAction(sc => AnalyzeInvocationForIgnoredReturnValue(sc, immutableSymbols), SyntaxKind.InvocationExpression);
- });
- }
-
- public static void AnalyzeInvocationForIgnoredReturnValue(SyntaxNodeAnalysisContext context, ImmutableArray immutableTypeSymbols)
- {
- SemanticModel model = context.SemanticModel;
- var candidateInvocation = (InvocationExpressionSyntax)context.Node;
-
- //We're looking for invocations that are direct children of expression statements
- if (!candidateInvocation.Parent.IsKind(SyntaxKind.ExpressionStatement))
- {
- return;
- }
-
- //If we can't find the method symbol, quit
- if (model.GetSymbolInfo(candidateInvocation, context.CancellationToken).Symbol is not IMethodSymbol methodSymbol)
- {
- return;
- }
-
- //If the method doesn't start with something like "With" or "Replace", quit
- string methodName = methodSymbol.Name;
- if (!s_immutableMethodNames.Any(n => methodName.StartsWith(n, StringComparison.Ordinal)))
- {
- return;
- }
-
- //If we're not in one of the known immutable types, quit
- if (methodSymbol.ReceiverType is not INamedTypeSymbol parentType)
- {
- return;
- }
-
- var baseTypesAndSelf = methodSymbol.ReceiverType.GetBaseTypes().ToList();
- baseTypesAndSelf.Add(parentType);
-
- if (!baseTypesAndSelf.Any(immutableTypeSymbols.Contains))
- {
- return;
- }
-
- Location location = candidateInvocation.GetLocation();
- Diagnostic diagnostic = Diagnostic.Create(DoNotIgnoreReturnValueDiagnosticRule, location, methodSymbol.ReceiverType.Name, methodSymbol.Name);
- context.ReportDiagnostic(diagnostic);
- }
- }
-}
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.Analyzers/Core/AnalyzerReleases.Unshipped.md
index 0a644588b4..95e7943b47 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/AnalyzerReleases.Unshipped.md
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/AnalyzerReleases.Unshipped.md
@@ -4,5 +4,6 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
+RS1014 | MicrosoftCodeAnalysisCorrectness | Warning | ImmutableObjectMethodAnalyzer
RS1035 | MicrosoftCodeAnalysisCorrectness | Error | SymbolIsBannedInAnalyzersAnalyzer
RS1036 | MicrosoftCodeAnalysisCorrectness | Warning | SymbolIsBannedInAnalyzersAnalyzer
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx
index 18a503334d..f667d01101 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/CodeAnalysisDiagnosticsResources.resx
@@ -269,7 +269,7 @@
'{0}' is immutable and '{1}' will not have any effect on it. Consider using the return value from '{1}'.
- Do not ignore values returned by methods on immutable objects.
+ Do not ignore values returned by methods on immutable objects
DiagnosticId for analyzers must be a non-null constant
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/ImmutableObjectMethodAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/Core/ImmutableObjectMethodAnalyzer.cs
new file mode 100644
index 0000000000..d81369491b
--- /dev/null
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/ImmutableObjectMethodAnalyzer.cs
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using Analyzer.Utilities;
+using Analyzer.Utilities.Extensions;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace Microsoft.CodeAnalysis.Analyzers
+{
+ using static CodeAnalysisDiagnosticsResources;
+
+ ///
+ /// RS1014:
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
+ public sealed class ImmutableObjectMethodAnalyzer : DiagnosticAnalyzer
+ {
+ public static readonly DiagnosticDescriptor DoNotIgnoreReturnValueDiagnosticRule = new(
+ DiagnosticIds.DoNotIgnoreReturnValueOnImmutableObjectMethodInvocation,
+ CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle)),
+ CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationMessage)),
+ DiagnosticCategory.MicrosoftCodeAnalysisCorrectness,
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true,
+ description: CreateLocalizableResourceString(nameof(DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationDescription)),
+ customTags: WellKnownDiagnosticTagsExtensions.Telemetry);
+
+ public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DoNotIgnoreReturnValueDiagnosticRule);
+
+ private const string SolutionFullName = @"Microsoft.CodeAnalysis.Solution";
+ private const string ProjectFullName = @"Microsoft.CodeAnalysis.Project";
+ private const string DocumentFullName = @"Microsoft.CodeAnalysis.Document";
+ private const string SyntaxNodeFullName = @"Microsoft.CodeAnalysis.SyntaxNode";
+ private const string CompilationFullName = @"Microsoft.CodeAnalysis.Compilation";
+
+ private static readonly ImmutableArray s_immutableMethodNames = ImmutableArray.Create(
+ "Add",
+ "Remove",
+ "Replace",
+ "With");
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.EnableConcurrentExecution();
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+
+ context.RegisterCompilationStartAction(context =>
+ {
+ var compilation = context.Compilation;
+ var builder = ImmutableArray.CreateBuilder();
+ var provider = WellKnownTypeProvider.GetOrCreate(compilation);
+ AddIfNotNull(builder, provider.GetOrCreateTypeByMetadataName(SolutionFullName));
+ AddIfNotNull(builder, provider.GetOrCreateTypeByMetadataName(ProjectFullName));
+ AddIfNotNull(builder, provider.GetOrCreateTypeByMetadataName(DocumentFullName));
+ AddIfNotNull(builder, provider.GetOrCreateTypeByMetadataName(SyntaxNodeFullName));
+ AddIfNotNull(builder, provider.GetOrCreateTypeByMetadataName(CompilationFullName));
+ var immutableTypeSymbols = builder.ToImmutable();
+ if (immutableTypeSymbols.Length > 0)
+ {
+ context.RegisterOperationAction(context => AnalyzeInvocationForIgnoredReturnValue(context, immutableTypeSymbols), OperationKind.Invocation);
+ }
+ });
+
+ static void AddIfNotNull(ImmutableArray.Builder builder, INamedTypeSymbol? symbol)
+ {
+ if (symbol is not null)
+ {
+ builder.Add(symbol);
+ }
+ }
+ }
+
+ public static void AnalyzeInvocationForIgnoredReturnValue(OperationAnalysisContext context, ImmutableArray immutableTypeSymbols)
+ {
+ var invocation = (IInvocationOperation)context.Operation;
+ if (invocation.Parent is not IExpressionStatementOperation)
+ {
+ return;
+ }
+
+ // If the method doesn't start with something like "With" or "Replace", quit
+ string methodName = invocation.TargetMethod.Name;
+ if (!s_immutableMethodNames.Any(n => methodName.StartsWith(n, StringComparison.Ordinal)))
+ {
+ return;
+ }
+
+ INamedTypeSymbol? type = null;
+ if (invocation.Instance is not null)
+ {
+ type = invocation.Instance.Type as INamedTypeSymbol;
+ }
+ else if (invocation.TargetMethod.IsExtensionMethod && invocation.TargetMethod.Parameters is [{ Type: var parameterType }, ..])
+ {
+ type = parameterType as INamedTypeSymbol;
+ }
+
+ // If we're not in one of the known immutable types, quit
+ if (type is not null && type.GetBaseTypesAndThis().Any(immutableTypeSymbols.Contains))
+ {
+ context.ReportDiagnostic(invocation.CreateDiagnostic(DoNotIgnoreReturnValueDiagnosticRule, type.Name, methodName));
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf
index 7c7bb71967..e182f32064 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.cs.xlf
@@ -571,8 +571,8 @@
-
- Neignorujte hodnoty vrácené metodami u neměnných objektů.
+
+ Neignorujte hodnoty vrácené metodami u neměnných objektů.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf
index f248a7001c..577af1f446 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.de.xlf
@@ -571,8 +571,8 @@
-
- Keine von Methoden zu unveränderlichen Objekten zurückgegebenen Werte ignorieren
+
+ Keine von Methoden zu unveränderlichen Objekten zurückgegebenen Werte ignorieren
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf
index 00bb024171..fe5727536f 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.es.xlf
@@ -571,8 +571,8 @@
-
- No omitir los valores devueltos por métodos en objetos inmutables.
+
+ No omitir los valores devueltos por métodos en objetos inmutables.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf
index ce38e4b292..26270fb5f4 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.fr.xlf
@@ -571,8 +571,8 @@
-
- N'ignorez pas les valeurs retournées par les méthodes sur les objets non modifiables.
+
+ N'ignorez pas les valeurs retournées par les méthodes sur les objets non modifiables.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf
index f6ba0a4364..0d89cb3619 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.it.xlf
@@ -571,8 +571,8 @@
-
- Non ignorare i valori restituiti dai metodi su oggetti non modificabili.
+
+ Non ignorare i valori restituiti dai metodi su oggetti non modificabili.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf
index a858898b70..249d6c8cf7 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ja.xlf
@@ -571,8 +571,8 @@
-
- 不変オブジェクトのメソッドによって返される値を無視しないでください。
+
+ 不変オブジェクトのメソッドによって返される値を無視しないでください。
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf
index 6be7183fd5..0f45b37bdf 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ko.xlf
@@ -571,8 +571,8 @@
-
- 변경할 수 없는 개체의 메서드에서 반환된 값을 무시하지 마세요.
+
+ 변경할 수 없는 개체의 메서드에서 반환된 값을 무시하지 마세요.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf
index 75e2d1f329..435c37cfaa 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pl.xlf
@@ -571,8 +571,8 @@
-
- Nie ignoruj wartości zwracanych przez metody dla niezmienialnych obiektów.
+
+ Nie ignoruj wartości zwracanych przez metody dla niezmienialnych obiektów.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf
index 033aec8345..ddd788db18 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.pt-BR.xlf
@@ -571,8 +571,8 @@
-
- Não ignore valores retornados por métodos em objetos imutáveis.
+
+ Não ignore valores retornados por métodos em objetos imutáveis.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf
index e21575c4b9..e498410c39 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.ru.xlf
@@ -571,8 +571,8 @@
-
- Не игнорируйте значения, возвращаемые методами для неизменяемых объектов.
+
+ Не игнорируйте значения, возвращаемые методами для неизменяемых объектов.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf
index 25479c6c48..1a12205dc9 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.tr.xlf
@@ -571,8 +571,8 @@
-
- Sabit nesneler üzerinde yöntemler tarafından döndürülen değerleri yoksaymayın.
+
+ Sabit nesneler üzerinde yöntemler tarafından döndürülen değerleri yoksaymayın.
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf
index 8f3cf4bc26..d0f695c89b 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hans.xlf
@@ -571,8 +571,8 @@
-
- 不要忽略通过不可变对象上的方法返回的值。
+
+ 不要忽略通过不可变对象上的方法返回的值。
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf
index d6cccc2f25..4fcb7e3a42 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf
+++ b/src/Microsoft.CodeAnalysis.Analyzers/Core/xlf/CodeAnalysisDiagnosticsResources.zh-Hant.xlf
@@ -571,8 +571,8 @@
-
- 請勿略過不可變物件上方法所傳回的值。
+
+ 請勿略過不可變物件上方法所傳回的值。
diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/UseReturnValueFromImmutableObjectMethodTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/UseReturnValueFromImmutableObjectMethodTests.cs
index 1690cae80f..ca427302d7 100644
--- a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/UseReturnValueFromImmutableObjectMethodTests.cs
+++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/UseReturnValueFromImmutableObjectMethodTests.cs
@@ -4,7 +4,11 @@
using Microsoft.CodeAnalysis.Testing;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
- Microsoft.CodeAnalysis.CSharp.Analyzers.CSharpImmutableObjectMethodAnalyzer,
+ Microsoft.CodeAnalysis.Analyzers.ImmutableObjectMethodAnalyzer,
+ Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
+
+using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
+ Microsoft.CodeAnalysis.Analyzers.ImmutableObjectMethodAnalyzer,
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
namespace Microsoft.CodeAnalysis.Analyzers.UnitTests
@@ -23,27 +27,58 @@ class TestSimple
void M()
{
Document document = default(Document);
- document.WithText(default(SourceText));
+ {|#0:document.WithText(default(SourceText))|};
Project project = default(Project);
- project.AddDocument(""Sample.cs"", default(SourceText));
+ {|#1:project.AddDocument(""Sample.cs"", default(SourceText))|};
Solution solution = default(Solution);
- solution.AddProject(""Sample"", ""Sample"", ""CSharp"");
+ {|#2:solution.AddProject(""Sample"", ""Sample"", ""CSharp"")|};
Compilation compilation = default(Compilation);
- compilation.RemoveAllSyntaxTrees();
+ {|#3:compilation.RemoveAllSyntaxTrees()|};
}
}
";
- DiagnosticResult documentExpected = GetCSharpExpectedDiagnostic(10, 9, "Document", "WithText");
- DiagnosticResult projectExpected = GetCSharpExpectedDiagnostic(13, 9, "Project", "AddDocument");
- DiagnosticResult solutionExpected = GetCSharpExpectedDiagnostic(16, 9, "Solution", "AddProject");
- DiagnosticResult compilationExpected = GetCSharpExpectedDiagnostic(19, 9, "Compilation", "RemoveAllSyntaxTrees");
+ DiagnosticResult documentExpected = GetCSharpExpectedDiagnostic(0, "Document", "WithText");
+ DiagnosticResult projectExpected = GetCSharpExpectedDiagnostic(1, "Project", "AddDocument");
+ DiagnosticResult solutionExpected = GetCSharpExpectedDiagnostic(2, "Solution", "AddProject");
+ DiagnosticResult compilationExpected = GetCSharpExpectedDiagnostic(3, "Compilation", "RemoveAllSyntaxTrees");
await VerifyCS.VerifyAnalyzerAsync(source, documentExpected, projectExpected, solutionExpected, compilationExpected);
}
+ [Fact]
+ public async Task VisualBasicVerifyDiagnosticsAsync()
+ {
+ var source = @"
+Imports Microsoft.CodeAnalysis
+Imports Microsoft.CodeAnalysis.Text
+
+Class TestSimple
+ Sub M()
+ Dim document As Document = Nothing
+ {|#0:document.WithText(Nothing)|}
+
+ Dim project As Project = Nothing
+ {|#1:project.AddDocument(""Sample.cs"", CType(Nothing, SourceText))|}
+
+ Dim solution As Solution = Nothing
+ {|#2:solution.AddProject(""Sample"", ""Sample"", ""CSharp"")|}
+
+ Dim compilation As Compilation = Nothing
+ {|#3:compilation.RemoveAllSyntaxTrees()|}
+ End Sub
+End Class
+";
+ DiagnosticResult documentExpected = GetVisualBasicExpectedDiagnostic(0, "Document", "WithText");
+ DiagnosticResult projectExpected = GetVisualBasicExpectedDiagnostic(1, "Project", "AddDocument");
+ DiagnosticResult solutionExpected = GetVisualBasicExpectedDiagnostic(2, "Solution", "AddProject");
+ DiagnosticResult compilationExpected = GetVisualBasicExpectedDiagnostic(3, "Compilation", "RemoveAllSyntaxTrees");
+
+ await VerifyVB.VerifyAnalyzerAsync(source, documentExpected, projectExpected, solutionExpected, compilationExpected);
+ }
+
[Fact]
public async Task CSharp_VerifyDiagnosticOnExtensionMethodAsync()
{
@@ -56,13 +91,30 @@ class TestExtensionMethodTrivia
void M()
{
SyntaxNode node = default(SyntaxNode);
- node.WithLeadingTrivia();
+ {|#0:node.WithLeadingTrivia()|};
}
}";
- DiagnosticResult expected = GetCSharpExpectedDiagnostic(10, 9, "SyntaxNode", "WithLeadingTrivia");
+ DiagnosticResult expected = GetCSharpExpectedDiagnostic(0, "SyntaxNode", "WithLeadingTrivia");
await VerifyCS.VerifyAnalyzerAsync(source, expected);
}
+ [Fact]
+ public async Task VisualBasic_VerifyDiagnosticOnExtensionMethodAsync()
+ {
+ var source = @"
+Imports Microsoft.CodeAnalysis
+Imports Microsoft.CodeAnalysis.Text
+
+Class TestExtensionMethodTrivia
+ Sub M()
+ Dim node As SyntaxNode = Nothing
+ {|#0:node.WithLeadingTrivia()|}
+ End Sub
+End Class";
+ DiagnosticResult expected = GetVisualBasicExpectedDiagnostic(0, "SyntaxNode", "WithLeadingTrivia");
+ await VerifyVB.VerifyAnalyzerAsync(source, expected);
+ }
+
[Fact]
public async Task CSharp_VerifyNoDiagnosticAsync()
{
@@ -92,11 +144,35 @@ public void OtherMethod(Document document)
await VerifyCS.VerifyAnalyzerAsync(source);
}
- private static DiagnosticResult GetCSharpExpectedDiagnostic(int line, int column, string objectName, string methodName) =>
-#pragma warning disable RS0030 // Do not use banned APIs
- VerifyCS.Diagnostic()
- .WithLocation(line, column)
-#pragma warning restore RS0030 // Do not use banned APIs
- .WithArguments(objectName, methodName);
+ [Fact]
+ public async Task VisualBasic_VerifyNoDiagnosticAsync()
+ {
+ var source = @"
+Imports Microsoft.CodeAnalysis
+Imports Microsoft.CodeAnalysis.Text
+
+Namespace ConsoleApplication1
+ Class TestNoDiagnostic
+ Public Function M() As Document
+ Dim document As Document = Nothing
+ Dim newDocument = document.WithText(Nothing)
+ document = document.WithText(Nothing)
+
+ OtherMethod(document.WithText(Nothing))
+ Return document.WithText(Nothing)
+ End Function
+
+ Public Sub OtherMethod(document As Document)
+ End Sub
+ End Class
+End Namespace";
+ await VerifyVB.VerifyAnalyzerAsync(source);
+ }
+
+ private static DiagnosticResult GetCSharpExpectedDiagnostic(int markupKey, string objectName, string methodName) =>
+ VerifyCS.Diagnostic().WithLocation(markupKey).WithArguments(objectName, methodName);
+
+ private static DiagnosticResult GetVisualBasicExpectedDiagnostic(int markupKey, string objectName, string methodName) =>
+ VerifyVB.Diagnostic().WithLocation(markupKey).WithArguments(objectName, methodName);
}
}