Skip to content

Commit

Permalink
Support VB for ImmutableObjectMethodAnalyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Dec 10, 2022
1 parent f361553 commit ad3be7b
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 155 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
RS1014 | MicrosoftCodeAnalysisCorrectness | Warning | ImmutableObjectMethodAnalyzer
RS1035 | MicrosoftCodeAnalysisCorrectness | Error | SymbolIsBannedInAnalyzersAnalyzer
RS1036 | MicrosoftCodeAnalysisCorrectness | Warning | SymbolIsBannedInAnalyzersAnalyzer
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
<value>'{0}' is immutable and '{1}' will not have any effect on it. Consider using the return value from '{1}'.</value>
</data>
<data name="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle" xml:space="preserve">
<value>Do not ignore values returned by methods on immutable objects.</value>
<value>Do not ignore values returned by methods on immutable objects</value>
</data>
<data name="DiagnosticIdMustBeAConstantTitle" xml:space="preserve">
<value>DiagnosticId for analyzers must be a non-null constant</value>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// RS1014: <inheritdoc cref="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle"/>
/// </summary>
[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<DiagnosticDescriptor> 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<string> 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<INamedTypeSymbol>();
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<INamedTypeSymbol>.Builder builder, INamedTypeSymbol? symbol)
{
if (symbol is not null)
{
builder.Add(symbol);
}
}
}

public static void AnalyzeInvocationForIgnoredReturnValue(OperationAnalysisContext context, ImmutableArray<INamedTypeSymbol> 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));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Neignorujte hodnoty vrácené metodami u neměnných objektů.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Neignorujte hodnoty vrácené metodami u neměnných objektů.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Keine von Methoden zu unveränderlichen Objekten zurückgegebenen Werte ignorieren</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Keine von Methoden zu unveränderlichen Objekten zurückgegebenen Werte ignorieren</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">No omitir los valores devueltos por métodos en objetos inmutables.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">No omitir los valores devueltos por métodos en objetos inmutables.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">N'ignorez pas les valeurs retournées par les méthodes sur les objets non modifiables.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">N'ignorez pas les valeurs retournées par les méthodes sur les objets non modifiables.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Non ignorare i valori restituiti dai metodi su oggetti non modificabili.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Non ignorare i valori restituiti dai metodi su oggetti non modificabili.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">不変オブジェクトのメソッドによって返される値を無視しないでください。</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">不変オブジェクトのメソッドによって返される値を無視しないでください。</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">변경할 수 없는 개체의 메서드에서 반환된 값을 무시하지 마세요.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">변경할 수 없는 개체의 메서드에서 반환된 값을 무시하지 마세요.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Nie ignoruj wartości zwracanych przez metody dla niezmienialnych obiektów.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Nie ignoruj wartości zwracanych przez metody dla niezmienialnych obiektów.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Não ignore valores retornados por métodos em objetos imutáveis.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Não ignore valores retornados por métodos em objetos imutáveis.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Не игнорируйте значения, возвращаемые методами для неизменяемых объектов.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Не игнорируйте значения, возвращаемые методами для неизменяемых объектов.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">Sabit nesneler üzerinde yöntemler tarafından döndürülen değerleri yoksaymayın.</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">Sabit nesneler üzerinde yöntemler tarafından döndürülen değerleri yoksaymayın.</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreReturnValueOnImmutableObjectMethodInvocationTitle">
<source>Do not ignore values returned by methods on immutable objects.</source>
<target state="translated">不要忽略通过不可变对象上的方法返回的值。</target>
<source>Do not ignore values returned by methods on immutable objects</source>
<target state="needs-review-translation">不要忽略通过不可变对象上的方法返回的值。</target>
<note />
</trans-unit>
<trans-unit id="OverrideGetFixAllProviderTitle">
Expand Down
Loading

0 comments on commit ad3be7b

Please sign in to comment.