From 27962a6468a3be1125c0967c16759b71b0b45d64 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Sun, 20 Dec 2020 19:28:39 +0200 Subject: [PATCH 1/3] Implement IdentifiersShouldNotContainUnderscoresFixer --- ...ifiersShouldNotContainUnderscores.Fixer.cs | 21 +- ...ifiersShouldNotContainUnderscores.Fixer.cs | 74 +- ...icrosoftCodeQualityAnalyzersResources.resx | 5 +- ...rosoftCodeQualityAnalyzersResources.cs.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.de.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.es.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.fr.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.it.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.ja.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.ko.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.pl.xlf | 5 + ...oftCodeQualityAnalyzersResources.pt-BR.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.ru.xlf | 5 + ...rosoftCodeQualityAnalyzersResources.tr.xlf | 5 + ...tCodeQualityAnalyzersResources.zh-Hans.xlf | 5 + ...tCodeQualityAnalyzersResources.zh-Hant.xlf | 5 + ...tifiersShouldNotContainUnderscoresTests.cs | 1028 ++++++++++++++--- ...ifiersShouldNotContainUnderscores.Fixer.vb | 21 + 18 files changed, 1018 insertions(+), 196 deletions(-) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs index 5eb81b9031..08f581228e 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs @@ -4,6 +4,7 @@ using Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines { @@ -13,5 +14,23 @@ namespace Microsoft.CodeQuality.CSharp.Analyzers.ApiDesignGuidelines [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpIdentifiersShouldNotContainUnderscoresFixer : IdentifiersShouldNotContainUnderscoresFixer { + protected override string GetNewName(string name) + { + string result = RemoveUnderscores(name); + if (result.Length == 0) + return string.Empty; + + if (!SyntaxFacts.IsValidIdentifier(result)) + { + return $"@{result}"; + } + + return result; + } + + protected override SyntaxNode GetDeclarationNode(SyntaxNode node) + => node.IsKind(SyntaxKind.IdentifierName) + ? node.Parent + : node; } -} \ No newline at end of file +} diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs index 711962e124..eef21f8070 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs @@ -1,8 +1,15 @@ // 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.Globalization; +using System.Text; +using System.Threading; using System.Threading.Tasks; +using Analyzer.Utilities; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Rename; namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines { @@ -11,7 +18,10 @@ namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines /// public abstract class IdentifiersShouldNotContainUnderscoresFixer : CodeFixProvider { - public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Empty; + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(IdentifiersShouldNotContainUnderscoresAnalyzer.RuleId); + + protected abstract string GetNewName(string name); + protected abstract SyntaxNode GetDeclarationNode(SyntaxNode node); public sealed override FixAllProvider GetFixAllProvider() { @@ -19,11 +29,65 @@ public sealed override FixAllProvider GetFixAllProvider() return WellKnownFixAllProviders.BatchFixer; } - public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { - // Fixer not yet implemented. - return Task.CompletedTask; + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); + + var node = root.FindNode(context.Span); + if (node == null) + { + return; + } + + var symbol = model.GetDeclaredSymbol(GetDeclarationNode(node), context.CancellationToken); + if (symbol == null) + { + return; + } + var newName = GetNewName(symbol.Name); + if (newName.Length == 0) + { + return; + } + + // Make sure there is no symbol with the same name already exists. + if (!model.LookupSymbols(context.Span.Start, symbol.ContainingType, newName).IsEmpty) + { + return; + } + + string title = MicrosoftCodeQualityAnalyzersResources.IdentifiersShouldNotContainUnderscoresCodeFixTitle; + context.RegisterCodeFix(new MyCodeAction(title, + ct => Renamer.RenameSymbolAsync(context.Document.Project.Solution, symbol, newName, null, ct), + equivalenceKey: title), + context.Diagnostics); + } + + protected static string RemoveUnderscores(string name) + { + var builder = new StringBuilder(); + bool isPreviousUnderscore = false; + foreach (char c in name) + { + if (c == '_') + { + isPreviousUnderscore = true; + continue; + } + builder.Append(isPreviousUnderscore ? char.ToUpper(c, CultureInfo.InvariantCulture) : c); + isPreviousUnderscore = false; + } + return builder.ToString(); + } + + private class MyCodeAction : SolutionChangeAction + { + public MyCodeAction(string title, Func> createChangedSolution, string equivalenceKey) + : base(title, createChangedSolution, equivalenceKey) + { + } } } -} \ No newline at end of file +} diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx index 730afdbfb1..7be7c4fa00 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/MicrosoftCodeQualityAnalyzersResources.resx @@ -1433,7 +1433,10 @@ '{0}' calls '{1}' but does not use the value the method returns. This method is defined as a user-option. Use the result in a conditional statement, assign the result to a variable, or pass it as an argument to another method. + + Remove underscores + Apply 'AttributeUsageAttribute' - + \ No newline at end of file diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf index 267923e61d..6633f5d77a 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.cs.xlf @@ -292,6 +292,11 @@ Události by neměly mít předponu Before nebo After + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Odeberte finalizační metodu z typu {0}, přepište Dispose(bool disposing) a vložte finalizační logiku do cesty kódu, kde je disposing hodnoty false. V opačném případě by to mohlo vést k duplicitním voláním Dispose, protože základní typ {1} také poskytuje finalizační metodu. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf index 8b0873bd08..b3b81b0bb9 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.de.xlf @@ -292,6 +292,11 @@ Ereignisse dürfen kein Präfix "Before" oder "After" aufweisen. + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Entfernen Sie den Finalizer vom Typ "{0}", setzen Sie "Dispose(bool disposing)" außer Kraft, und platzieren Sie die Finalisierungslogik im Codepfad, wenn "disposing" FALSE lautet. Andernfalls kann es zu doppelten Dispose-Aufrufen kommen, weil der Basistyp "{1}" ebenfalls einen Finalizer bereitstellt. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf index 7edac21f3f..7e2ea5b1a4 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.es.xlf @@ -292,6 +292,11 @@ Los eventos no deben tener el prefijo "Antes" ni "Después" + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Elimine el finalizador del tipo "{0}", reemplace el valor de "Dispose(bool disposing)" y coloque la lógica de finalización en la ruta de código de manera que el valor de "disposing" se establezca como falso. De lo contrario, se duplicarían las invocaciones de "Dispose" ya que el tipo Base "{1}" también ofrece un finalizador. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf index dd11cb6b8c..b34781c90c 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.fr.xlf @@ -292,6 +292,11 @@ Les événements ne doivent pas avoir un préfixe 'Before' ou 'After' + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Supprimez le finaliseur du type '{0}', remplacez Dispose(bool disposing) et placez la logique de finalisation dans le chemin de code où 'disposing' est false. Sinon, vous risquez d'avoir des invocations de Dispose en double, car le type de base '{1}' fournit aussi un finaliseur. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf index ce3fd8338f..5091b34d37 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.it.xlf @@ -292,6 +292,11 @@ Non usare il prefisso 'Before' o 'After' negli eventi + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Rimuovere il finalizzatore dal tipo '{0}', eseguire l'override di Dispose(bool disposing) e inserire la logica di finalizzazione nel percorso del codice in cui 'disposing' è false. In caso contrario, potrebbero verificarsi chiamate duplicate a Dispose perché il tipo di base '{1}' fornisce anche un finalizzatore. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf index b1c44f4967..25c838ae45 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ja.xlf @@ -292,6 +292,11 @@ イベントに 'Before' または 'After' プレフィックスを付けることはできない + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. 型 '{0}' からファイナライザーを削除し、Dispose(bool disposing) をオーバーライドします。その後、'disposing' が false のコード パスに finalization 論理を配置します。その他の場合、基本型 '{1}' でもファイナライザーが提供されるため、Dispose 呼び出しが重複する可能性があります。 diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf index aa9b519120..888c6b77f3 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ko.xlf @@ -292,6 +292,11 @@ 이벤트에 'Before' 또는 'After' 접두사를 사용하지 마세요. + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. '{0}' 형식에서 종료자를 제거하고 Dispose(bool disposing)를 재정의한 후 종료 논리를 'disposing'이 false인 코드 경로에 추가하세요. 그렇지 않으면, 기본 형식 '{1}'도 종료자를 제공할 때 중복된 Dispose 호출이 발생할 수 있습니다. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf index 4a3f9224f3..e4640e5b45 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pl.xlf @@ -292,6 +292,11 @@ Zdarzenia nie powinny mieć prefiksu „Przed” ani „Po” + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Usuń finalizator z typu „{0}”, przesłoń funkcję Dispose(bool disposing) i umieść logikę finalizacji w ścieżce kodu, gdzie element „disposing” ma wartość false. W przeciwnym razie mogą pojawić się zduplikowane wywołania funkcji Dispose, ponieważ typ bazowy „{1}” także udostępnia finalizator. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf index ead188f5e5..6e845ae77f 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.pt-BR.xlf @@ -292,6 +292,11 @@ Eventos não devem ter o prefixo 'Before' ou 'After' + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Remova o finalizador do tipo '{0}', substitua Dispose(bool disposing) e coloque a lógica de finalização no caminho do código em que 'disposing' é false. Caso contrário, ele poderá duplicar invocações Dispose, já que o tipo Base '{1}' também fornece um finalizador. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf index d4504a22db..decd9dbda6 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.ru.xlf @@ -292,6 +292,11 @@ 3 - ReadyForReview + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. Удалите метод завершения из типа '{0}', переопределите Dispose(bool disposing) и поместите логику завершения в путь кода, туда где 'disposing' имеет значение false. В противном случае это может привести к дублированию вызовов метода Dispose, так как базовый тип '{1}' также предоставляет метод завершения. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf index 6c3172a70d..c556c6651d 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.tr.xlf @@ -292,6 +292,11 @@ Olaylar 'Before' ya da 'After' ön ekine sahip olmamalıdır + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. '{0}' türünden sonlandırıcıyı kaldırın, Dispose(bool disposing) metodunu geçersiz kılın ve sonlandırma mantığını 'disposing' değerinin false olduğu kod yoluna yerleştirin. Aksi takdirde, '{1}' Temel türü de bir sonlandırıcı sağladığından yinelenen Dispose çağrılarına yol açabilir. diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf index 5fc3a3e6eb..74ed288b11 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hans.xlf @@ -292,6 +292,11 @@ 事件不应具有 "Before" 或 "After" 前缀 + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. 从类型“{0}”中删除终结器,替代 Dispose(bool disposing),并在 "disposing" 为 false 的代码路径中放置终结逻辑。否则,它可能导致出现重复的 Dispose 调用,因为基类型“{1}”也提供终结器。 diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf index 8ff5cc916b..fdddb09793 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/xlf/MicrosoftCodeQualityAnalyzersResources.zh-Hant.xlf @@ -292,6 +292,11 @@ 事件開頭不應出現 'Before' 或 'After' + + Remove underscores + Remove underscores + + Remove the finalizer from type '{0}', override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false. Otherwise, it might lead to duplicate Dispose invocations as the Base type '{1}' also provides a finalizer. 從類型 '{0}' 移除完成項,覆寫 Dispose(bool disposing),然後在程式碼路徑中放置完成項邏輯,其中 'disposing' 為 false。否則這可能導致 Dispose 引動過程重複,原因是基底類型 ‘{1}’ 也提供了完成項。 diff --git a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscoresTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscoresTests.cs index 8651ab8ffa..fcf592013d 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscoresTests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscoresTests.cs @@ -20,7 +20,7 @@ public class IdentifiersShouldNotContainUnderscoresTests { #region CSharp Tests [Fact] - public async Task CA1707_ForAssembly_CSharp() + public async Task CA1707_ForAssembly_CSharp() // TODO: How to test the code fixer for this? { await new VerifyCS.Test { @@ -62,10 +62,10 @@ public class DoesNotMatter [Fact] public async Task CA1707_ForNamespace_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" namespace OuterNamespace { - namespace HasUnderScore_ + namespace {|#0:HasUnderScore_|} { public class DoesNotMatter { @@ -79,16 +79,32 @@ public class DoesNotMatter { } }", - GetCA1707CSharpResultAt(line: 4, column: 15, symbolKind: SymbolKind.Namespace, identifierNames: "OuterNamespace.HasUnderScore_")); + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.NamespaceRule).WithLocation(0).WithArguments("OuterNamespace.HasUnderScore_"), @" +namespace OuterNamespace +{ + namespace HasUnderScore + { + public class DoesNotMatter + { + } + } +} + +namespace HasNoUnderScore +{ + public class DoesNotMatter + { + } +}"); } [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")] public async Task CA1707_ForTypes_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" public class OuterType { - public class UnderScoreInName_ + public class {|#0:UnderScoreInName_|} { } @@ -108,17 +124,84 @@ public class UnderScoreInNameButNotExternallyVisible_ } } ", - GetCA1707CSharpResultAt(line: 4, column: 18, symbolKind: SymbolKind.NamedType, identifierNames: "OuterType.UnderScoreInName_")); + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.TypeRule).WithLocation(0).WithArguments("OuterType.UnderScoreInName_"), @" +public class OuterType +{ + public class UnderScoreInName + { + } + + private class UnderScoreInNameButPrivate_ + { + } + + internal class UnderScoreInNameButInternal_ + { + } +} + +internal class OuterType2 +{ + public class UnderScoreInNameButNotExternallyVisible_ + { + } +} +"); } [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")] public async Task CA1707_ForFields_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await new VerifyCS.Test + { + TestState = + { + Sources = + { @" public class DoesNotMatter { + public const int {|#0:ConstField_|} = 5; + public static readonly int {|#1:StaticReadOnlyField_|} = 5; + + // No diagnostics for the below + private string InstanceField_; + private static string StaticField_; + public string _field; + protected string Another_field; +} + +public enum DoesNotMatterEnum +{ + {|#2:_EnumWithUnderscore|}, + {|#3:_|} +} + +public class C +{ + internal class C2 + { public const int ConstField_ = 5; - public static readonly int StaticReadOnlyField_ = 5; + } +} +", + }, + ExpectedDiagnostics = + { + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.ConstField_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.StaticReadOnlyField_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("DoesNotMatterEnum._EnumWithUnderscore"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("DoesNotMatterEnum._"), + } + }, + FixedState = + { + Sources = + { + @" +public class DoesNotMatter +{ + public const int ConstField = 5; + public static readonly int StaticReadOnlyField = 5; // No diagnostics for the below private string InstanceField_; @@ -129,8 +212,8 @@ public class DoesNotMatter public enum DoesNotMatterEnum { - _EnumWithUnderscore, - _ + EnumWithUnderscore, + {|#0:_|} } public class C @@ -141,33 +224,36 @@ internal class C2 } } ", - GetCA1707CSharpResultAt(line: 4, column: 26, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ConstField_"), - GetCA1707CSharpResultAt(line: 5, column: 36, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.StaticReadOnlyField_"), - GetCA1707CSharpResultAt(line: 16, column: 5, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatterEnum._EnumWithUnderscore"), - GetCA1707CSharpResultAt(line: 17, column: 5, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatterEnum._")); + }, + ExpectedDiagnostics = + { + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatterEnum._"), + }, + }, + }.RunAsync(); } [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")] public async Task CA1707_ForMethods_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" public class DoesNotMatter { - public void PublicM1_() { } + public void {|#0:PublicM1_|}() { } private void PrivateM2_() { } // No diagnostic internal void InternalM3_() { } // No diagnostic - protected void ProtectedM4_() { } + protected void {|#1:ProtectedM4_|}() { } } public interface I1 { - void M_(); + void {|#2:M_|}(); } public class ImplementI1 : I1 { public void M_() { } // No diagnostic - public virtual void M2_() { } + public virtual void {|#3:M2_|}() { } } public class Derives : ImplementI1 @@ -182,34 +268,68 @@ public class DoesNotMatter2 public void PublicM1_() { } // No diagnostic protected void ProtectedM4_() { } // No diagnostic } -}", - GetCA1707CSharpResultAt(line: 4, column: 17, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicM1_()"), - GetCA1707CSharpResultAt(line: 7, column: 20, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedM4_()"), - GetCA1707CSharpResultAt(line: 12, column: 10, symbolKind: SymbolKind.Member, identifierNames: "I1.M_()"), - GetCA1707CSharpResultAt(line: 18, column: 25, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.M2_()")); +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicM1_()"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedM4_()"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.M_()"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.M2_()") +}, @" +public class DoesNotMatter +{ + public void PublicM1() { } + private void PrivateM2_() { } // No diagnostic + internal void InternalM3_() { } // No diagnostic + protected void ProtectedM4() { } +} + +public interface I1 +{ + void M(); +} + +public class ImplementI1 : I1 +{ + public void M() { } // No diagnostic + public virtual void M2() { } +} + +public class Derives : ImplementI1 +{ + public override void M2() { } // No diagnostic +} + +internal class C +{ + public class DoesNotMatter2 + { + public void PublicM1_() { } // No diagnostic + protected void ProtectedM4_() { } // No diagnostic + } +}"); } [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")] public async Task CA1707_ForProperties_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" public class DoesNotMatter { - public int PublicP1_ { get; set; } + public int {|#0:PublicP1_|} { get; set; } private int PrivateP2_ { get; set; } // No diagnostic internal int InternalP3_ { get; set; } // No diagnostic - protected int ProtectedP4_ { get; set; } + protected int {|#1:ProtectedP4_|} { get; set; } } public interface I1 { - int P_ { get; set; } + int {|#2:P_|} { get; set; } } public class ImplementI1 : I1 { public int P_ { get; set; } // No diagnostic - public virtual int P2_ { get; set; } + public virtual int {|#3:P2_|} { get; set; } } public class Derives : ImplementI1 @@ -224,36 +344,70 @@ public class DoesNotMatter2 public int PublicP1_ { get; set; }// No diagnostic protected int ProtectedP4_ { get; set; } // No diagnostic } -}", - GetCA1707CSharpResultAt(line: 4, column: 16, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicP1_"), - GetCA1707CSharpResultAt(line: 7, column: 19, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedP4_"), - GetCA1707CSharpResultAt(line: 12, column: 9, symbolKind: SymbolKind.Member, identifierNames: "I1.P_"), - GetCA1707CSharpResultAt(line: 18, column: 24, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.P2_")); +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicP1_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedP4_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.P_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.P2_") +}, @" +public class DoesNotMatter +{ + public int PublicP1 { get; set; } + private int PrivateP2_ { get; set; } // No diagnostic + internal int InternalP3_ { get; set; } // No diagnostic + protected int ProtectedP4 { get; set; } +} + +public interface I1 +{ + int P { get; set; } +} + +public class ImplementI1 : I1 +{ + public int P { get; set; } // No diagnostic + public virtual int P2 { get; set; } +} + +public class Derives : ImplementI1 +{ + public override int P2 { get; set; } // No diagnostic +} + +internal class C +{ + public class DoesNotMatter2 + { + public int PublicP1_ { get; set; }// No diagnostic + protected int ProtectedP4_ { get; set; } // No diagnostic + } +}"); } [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")] public async Task CA1707_ForEvents_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" using System; public class DoesNotMatter { - public event EventHandler PublicE1_; + public event EventHandler {|#0:PublicE1_|}; private event EventHandler PrivateE2_; // No diagnostic internal event EventHandler InternalE3_; // No diagnostic - protected event EventHandler ProtectedE4_; + protected event EventHandler {|#1:ProtectedE4_|}; } public interface I1 { - event EventHandler E_; + event EventHandler {|#2:E_|}; } public class ImplementI1 : I1 { public event EventHandler E_;// No diagnostic - public virtual event EventHandler E2_; + public virtual event EventHandler {|#3:E2_|}; } public class Derives : ImplementI1 @@ -268,107 +422,198 @@ public class DoesNotMatter public event EventHandler PublicE1_; // No diagnostic protected event EventHandler ProtectedE4_; // No diagnostic } -}", - GetCA1707CSharpResultAt(line: 6, column: 31, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicE1_"), - GetCA1707CSharpResultAt(line: 9, column: 34, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedE4_"), - GetCA1707CSharpResultAt(line: 14, column: 24, symbolKind: SymbolKind.Member, identifierNames: "I1.E_"), - GetCA1707CSharpResultAt(line: 20, column: 39, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.E2_")); +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicE1_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedE4_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.E_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.E2_") +}, @" +using System; + +public class DoesNotMatter +{ + public event EventHandler PublicE1; + private event EventHandler PrivateE2_; // No diagnostic + internal event EventHandler InternalE3_; // No diagnostic + protected event EventHandler ProtectedE4; +} + +public interface I1 +{ + event EventHandler E; +} + +public class ImplementI1 : I1 +{ + public event EventHandler E;// No diagnostic + public virtual event EventHandler E2; +} + +public class Derives : ImplementI1 +{ + public override event EventHandler E2; // No diagnostic +} + +internal class C +{ + public class DoesNotMatter + { + public event EventHandler PublicE1_; // No diagnostic + protected event EventHandler ProtectedE4_; // No diagnostic + } +}"); } [Fact] public async Task CA1707_ForDelegates_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" -public delegate void Dele(int intPublic_, string stringPublic_); + await VerifyCS.VerifyCodeFixAsync(@" +public delegate void Dele(int {|#0:intPublic_|}, string {|#1:stringPublic_|}); internal delegate void Dele2(int intInternal_, string stringInternal_); // No diagnostics -public delegate T Del(int t_); -", - GetCA1707CSharpResultAt(2, 31, SymbolKind.DelegateParameter, "Dele", "intPublic_"), - GetCA1707CSharpResultAt(2, 50, SymbolKind.DelegateParameter, "Dele", "stringPublic_"), - GetCA1707CSharpResultAt(4, 30, SymbolKind.DelegateParameter, "Del", "t_")); +public delegate T Del(int {|#2:t_|}); +", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(0).WithArguments("Dele", "intPublic_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(1).WithArguments("Dele", "stringPublic_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(2).WithArguments("Del", "t_") +}, @" +public delegate void Dele(int intPublic, string stringPublic); +internal delegate void Dele2(int intInternal_, string stringInternal_); // No diagnostics +public delegate T Del(int t); +"); } [Fact] public async Task CA1707_ForMemberparameters_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" public class DoesNotMatter { - public void PublicM1(int int_) { } + public void PublicM1(int {|#0:int_|}) { } private void PrivateM2(int int_) { } // No diagnostic internal void InternalM3(int int_) { } // No diagnostic - protected void ProtectedM4(int int_) { } + protected void ProtectedM4(int {|#1:int_|}) { } } public interface I { - void M(int int_); + void M(int {|#2:int_|}); } public class implementI : I { - public void M(int int_) + public void M(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 { } } public abstract class Base { - public virtual void M1(int int_) + public virtual void M1(int {|#3:int_|}) { } - public abstract void M2(int int_); + public abstract void M2(int {|#4:int_|}); } public class Der : Base { - public override void M2(int int_) + public override void M2(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 { throw new System.NotImplementedException(); } - public override void M1(int int_) + public override void M1(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 { base.M1(int_); } -}", - GetCA1707CSharpResultAt(4, 30, SymbolKind.MemberParameter, "DoesNotMatter.PublicM1(int)", "int_"), - GetCA1707CSharpResultAt(7, 36, SymbolKind.MemberParameter, "DoesNotMatter.ProtectedM4(int)", "int_"), - GetCA1707CSharpResultAt(12, 16, SymbolKind.MemberParameter, "I.M(int)", "int_"), - GetCA1707CSharpResultAt(24, 32, SymbolKind.MemberParameter, "Base.M1(int)", "int_"), - GetCA1707CSharpResultAt(28, 33, SymbolKind.MemberParameter, "Base.M2(int)", "int_")); +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(0).WithArguments("DoesNotMatter.PublicM1(int)", "int_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedM4(int)", "int_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(2).WithArguments("I.M(int)", "int_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(3).WithArguments("Base.M1(int)", "int_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(4).WithArguments("Base.M2(int)", "int_") +}, @" +public class DoesNotMatter +{ + public void PublicM1(int @int) { } + private void PrivateM2(int int_) { } // No diagnostic + internal void InternalM3(int int_) { } // No diagnostic + protected void ProtectedM4(int @int) { } +} + +public interface I +{ + void M(int @int); +} + +public class implementI : I +{ + public void M(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 + { + } +} + +public abstract class Base +{ + public virtual void M1(int @int) + { + } + + public abstract void M2(int @int); +} + +public class Der : Base +{ + public override void M2(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 + { + throw new System.NotImplementedException(); + } + + public override void M1(int int_) // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 + { + base.M1(int_); + } +}"); } [Fact] public async Task CA1707_ForTypeTypeParameters_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" -public class DoesNotMatter + await VerifyCS.VerifyCodeFixAsync(@" +public class DoesNotMatter<{|#0:T_|}> { } class NoDiag { -}", - GetCA1707CSharpResultAt(2, 28, SymbolKind.TypeTypeParameter, "DoesNotMatter", "T_")); +}", VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.TypeTypeParameterRule).WithLocation(0).WithArguments("DoesNotMatter", "T_"), @" +public class DoesNotMatter +{ +} + +class NoDiag +{ +}"); } [Fact] public async Task CA1707_ForMemberTypeParameters_CSharp() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" public class DoesNotMatter22 { - public void PublicM1() { } + public void PublicM1<{|#0:T1_|}>() { } private void PrivateM2() { } // No diagnostic internal void InternalM3() { } // No diagnostic - protected void ProtectedM4() { } + protected void ProtectedM4<{|#1:D_|}>() { } } public interface I { - void M(); + void M<{|#2:T_|}>(); } public class implementI : I @@ -381,30 +626,74 @@ public void M() public abstract class Base { - public virtual void M1() + public virtual void M1<{|#3:T_|}>() { } - public abstract void M2(); + public abstract void M2<{|#4:U_|}>(); } public class Der : Base { - public override void M2() + public override void M2() // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 { throw new System.NotImplementedException(); } - public override void M1() + public override void M1() // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 { base.M1(); } -}", - GetCA1707CSharpResultAt(4, 26, SymbolKind.MethodTypeParameter, "DoesNotMatter22.PublicM1()", "T1_"), - GetCA1707CSharpResultAt(7, 32, SymbolKind.MethodTypeParameter, "DoesNotMatter22.ProtectedM4()", "D_"), - GetCA1707CSharpResultAt(12, 12, SymbolKind.MethodTypeParameter, "I.M()", "T_"), - GetCA1707CSharpResultAt(25, 28, SymbolKind.MethodTypeParameter, "Base.M1()", "T_"), - GetCA1707CSharpResultAt(29, 29, SymbolKind.MethodTypeParameter, "Base.M2()", "U_")); +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(0).WithArguments("DoesNotMatter22.PublicM1()", "T1_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(1).WithArguments("DoesNotMatter22.ProtectedM4()", "D_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(2).WithArguments("I.M()", "T_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(3).WithArguments("Base.M1()", "T_"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(4).WithArguments("Base.M2()", "U_") +}, @" +public class DoesNotMatter22 +{ + public void PublicM1() { } + private void PrivateM2() { } // No diagnostic + internal void InternalM3() { } // No diagnostic + protected void ProtectedM4() { } +} + +public interface I +{ + void M(); +} + +public class implementI : I +{ + public void M() + { + throw new System.NotImplementedException(); + } +} + +public abstract class Base +{ + public virtual void M1() + { + } + + public abstract void M2(); +} + +public class Der : Base +{ + public override void M2() // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 + { + throw new System.NotImplementedException(); + } + + public override void M1() // This is not renamed due to https://github.com/dotnet/roslyn/issues/46663 + { + base.M1(); + } +}"); } [Fact, WorkItem(947, "https://github.com/dotnet/roslyn-analyzers/issues/947")] @@ -516,7 +805,7 @@ public SomeClass(object o) [Fact, WorkItem(3121, "https://github.com/dotnet/roslyn-analyzers/issues/3121")] public async Task CA1707_CSharp_GlobalAsaxSpecialMethods() { - await VerifyCS.VerifyAnalyzerAsync(@" + await VerifyCS.VerifyCodeFixAsync(@" using System; namespace System.Web @@ -538,6 +827,36 @@ protected void Session_Start(object sender, EventArgs e) {} } public class InvalidContext +{ + protected void {|#0:Application_AuthenticateRequest|}(object sender, EventArgs e) {} + protected void {|#1:Application_BeginRequest|}(object sender, EventArgs e) {} + protected void {|#2:Application_End|}(object sender, EventArgs e) {} + protected void {|#3:Application_EndRequest|}(object sender, EventArgs e) {} + protected void {|#4:Application_Error|}(object sender, EventArgs e) {} + protected void {|#5:Application_Init|}(object sender, EventArgs e) {} + protected void {|#6:Application_Start|}(object sender, EventArgs e) {} + protected void {|#7:Session_End|}(object sender, EventArgs e) {} + protected void {|#8:Session_Start|}(object sender, EventArgs e) {} +}", new[] +{ + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("InvalidContext.Application_AuthenticateRequest(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("InvalidContext.Application_BeginRequest(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("InvalidContext.Application_End(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("InvalidContext.Application_EndRequest(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(4).WithArguments("InvalidContext.Application_Error(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(5).WithArguments("InvalidContext.Application_Init(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(6).WithArguments("InvalidContext.Application_Start(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(7).WithArguments("InvalidContext.Session_End(object, System.EventArgs)"), + VerifyCS.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(8).WithArguments("InvalidContext.Session_Start(object, System.EventArgs)") +}, @" +using System; + +namespace System.Web +{ + public class HttpApplication {} +} + +public class ValidContext : System.Web.HttpApplication { protected void Application_AuthenticateRequest(object sender, EventArgs e) {} protected void Application_BeginRequest(object sender, EventArgs e) {} @@ -548,17 +867,21 @@ protected void Application_Init(object sender, EventArgs e) {} protected void Application_Start(object sender, EventArgs e) {} protected void Session_End(object sender, EventArgs e) {} protected void Session_Start(object sender, EventArgs e) {} -}", - GetCA1707CSharpResultAt(24, 20, SymbolKind.Member, "InvalidContext.Application_AuthenticateRequest(object, System.EventArgs)"), - GetCA1707CSharpResultAt(25, 20, SymbolKind.Member, "InvalidContext.Application_BeginRequest(object, System.EventArgs)"), - GetCA1707CSharpResultAt(26, 20, SymbolKind.Member, "InvalidContext.Application_End(object, System.EventArgs)"), - GetCA1707CSharpResultAt(27, 20, SymbolKind.Member, "InvalidContext.Application_EndRequest(object, System.EventArgs)"), - GetCA1707CSharpResultAt(28, 20, SymbolKind.Member, "InvalidContext.Application_Error(object, System.EventArgs)"), - GetCA1707CSharpResultAt(29, 20, SymbolKind.Member, "InvalidContext.Application_Init(object, System.EventArgs)"), - GetCA1707CSharpResultAt(30, 20, SymbolKind.Member, "InvalidContext.Application_Start(object, System.EventArgs)"), - GetCA1707CSharpResultAt(31, 20, SymbolKind.Member, "InvalidContext.Session_End(object, System.EventArgs)"), - GetCA1707CSharpResultAt(32, 20, SymbolKind.Member, "InvalidContext.Session_Start(object, System.EventArgs)")); - } +} + +public class InvalidContext +{ + protected void ApplicationAuthenticateRequest(object sender, EventArgs e) {} + protected void ApplicationBeginRequest(object sender, EventArgs e) {} + protected void ApplicationEnd(object sender, EventArgs e) {} + protected void ApplicationEndRequest(object sender, EventArgs e) {} + protected void ApplicationError(object sender, EventArgs e) {} + protected void ApplicationInit(object sender, EventArgs e) {} + protected void ApplicationStart(object sender, EventArgs e) {} + protected void SessionEnd(object sender, EventArgs e) {} + protected void SessionStart(object sender, EventArgs e) {} +}"); + } #endregion @@ -604,9 +927,9 @@ End Class [Fact] public async Task CA1707_ForNamespace_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Namespace OuterNamespace - Namespace HasUnderScore_ + Namespace {|#0:HasUnderScore_|} Public Class DoesNotMatter End Class End Namespace @@ -616,30 +939,48 @@ Namespace HasNoUnderScore Public Class DoesNotMatter End Class End Namespace", - GetCA1707BasicResultAt(line: 3, column: 15, symbolKind: SymbolKind.Namespace, identifierNames: "OuterNamespace.HasUnderScore_")); + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.NamespaceRule).WithLocation(0).WithArguments("OuterNamespace.HasUnderScore_"), @" +Namespace OuterNamespace + Namespace HasUnderScore + Public Class DoesNotMatter + End Class + End Namespace +End Namespace + +Namespace HasNoUnderScore + Public Class DoesNotMatter + End Class +End Namespace"); } [Fact] public async Task CA1707_ForTypes_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class OuterType - Public Class UnderScoreInName_ + Public Class {|#0:UnderScoreInName_|} End Class Private Class UnderScoreInNameButPrivate_ End Class End Class", - GetCA1707BasicResultAt(line: 3, column: 18, symbolKind: SymbolKind.NamedType, identifierNames: "OuterType.UnderScoreInName_")); + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.TypeRule).WithLocation(0).WithArguments("OuterType.UnderScoreInName_"), @" +Public Class OuterType + Public Class UnderScoreInName + End Class + + Private Class UnderScoreInNameButPrivate_ + End Class +End Class"); } [Fact] public async Task CA1707_ForFields_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class DoesNotMatter - Public Const ConstField_ As Integer = 5 - Public Shared ReadOnly SharedReadOnlyField_ As Integer = 5 + Public Const {|#0:ConstField_|} As Integer = 5 + Public Shared ReadOnly {|#1:SharedReadOnlyField_|} As Integer = 5 ' No diagnostics for the below Private InstanceField_ As String @@ -649,19 +990,35 @@ Protected Another_field As String End Class Public Enum DoesNotMatterEnum - _EnumWithUnderscore -End Enum", - GetCA1707BasicResultAt(line: 3, column: 18, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ConstField_"), - GetCA1707BasicResultAt(line: 4, column: 28, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.SharedReadOnlyField_"), - GetCA1707BasicResultAt(line: 14, column: 5, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatterEnum._EnumWithUnderscore")); + {|#2:_EnumWithUnderscore|} +End Enum", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.ConstField_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.SharedReadOnlyField_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("DoesNotMatterEnum._EnumWithUnderscore") +}, @" +Public Class DoesNotMatter + Public Const ConstField As Integer = 5 + Public Shared ReadOnly SharedReadOnlyField As Integer = 5 + + ' No diagnostics for the below + Private InstanceField_ As String + Private Shared StaticField_ As String + Public _field As String + Protected Another_field As String +End Class + +Public Enum DoesNotMatterEnum + EnumWithUnderscore +End Enum"); } [Fact] public async Task CA1707_ForMethods_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class DoesNotMatter - Public Sub PublicM1_() + Public Sub {|#0:PublicM1_|}() End Sub ' No diagnostic Private Sub PrivateM2_() @@ -669,12 +1026,12 @@ End Sub ' No diagnostic Friend Sub InternalM3_() End Sub - Protected Sub ProtectedM4_() + Protected Sub {|#1:ProtectedM4_|}() End Sub End Class Public Interface I1 - Sub M_() + Sub {|#2:M_|}() End Interface Public Class ImplementI1 @@ -682,7 +1039,7 @@ Implements I1 Public Sub M_() Implements I1.M_ End Sub ' No diagnostic - Public Overridable Sub M2_() + Public Overridable Sub {|#3:M2_|}() End Sub End Class @@ -691,19 +1048,53 @@ Inherits ImplementI1 ' No diagnostic Public Overrides Sub M2_() End Sub -End Class", - GetCA1707BasicResultAt(line: 3, column: 16, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicM1_()"), - GetCA1707BasicResultAt(line: 11, column: 19, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedM4_()"), - GetCA1707BasicResultAt(line: 16, column: 9, symbolKind: SymbolKind.Member, identifierNames: "I1.M_()"), - GetCA1707BasicResultAt(line: 24, column: 28, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.M2_()")); +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicM1_()"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedM4_()"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.M_()"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.M2_()") +}, @" +Public Class DoesNotMatter + Public Sub PublicM1() + End Sub + ' No diagnostic + Private Sub PrivateM2_() + End Sub + ' No diagnostic + Friend Sub InternalM3_() + End Sub + Protected Sub ProtectedM4() + End Sub +End Class + +Public Interface I1 + Sub M() +End Interface + +Public Class ImplementI1 + Implements I1 + Public Sub M() Implements I1.M + End Sub + ' No diagnostic + Public Overridable Sub M2() + End Sub +End Class + +Public Class Derives + Inherits ImplementI1 + ' No diagnostic + Public Overrides Sub M2() + End Sub +End Class"); } [Fact] public async Task CA1707_ForProperties_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class DoesNotMatter - Public Property PublicP1_() As Integer + Public Property {|#0:PublicP1_|}() As Integer Get Return 0 End Get @@ -726,7 +1117,7 @@ End Get Set End Set End Property - Protected Property ProtectedP4_() As Integer + Protected Property {|#1:ProtectedP4_|}() As Integer Get Return 0 End Get @@ -736,7 +1127,7 @@ End Property End Class Public Interface I1 - Property P_() As Integer + Property {|#2:P_|}() As Integer End Interface Public Class ImplementI1 @@ -749,7 +1140,7 @@ End Get Set End Set End Property - Public Overridable Property P2_() As Integer + Public Overridable Property {|#3:P2_|}() As Integer Get Return 0 End Get @@ -768,68 +1159,171 @@ End Get Set End Set End Property -End Class", - GetCA1707BasicResultAt(line: 3, column: 21, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicP1_"), - GetCA1707BasicResultAt(line: 26, column: 24, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedP4_"), - GetCA1707BasicResultAt(line: 36, column: 14, symbolKind: SymbolKind.Member, identifierNames: "I1.P_"), - GetCA1707BasicResultAt(line: 49, column: 33, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.P2_")); +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicP1_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedP4_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.P_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.P2_") +}, @" +Public Class DoesNotMatter + Public Property PublicP1() As Integer + Get + Return 0 + End Get + Set + End Set + End Property + ' No diagnostic + Private Property PrivateP2_() As Integer + Get + Return 0 + End Get + Set + End Set + End Property + ' No diagnostic + Friend Property InternalP3_() As Integer + Get + Return 0 + End Get + Set + End Set + End Property + Protected Property ProtectedP4() As Integer + Get + Return 0 + End Get + Set + End Set + End Property +End Class + +Public Interface I1 + Property P() As Integer +End Interface + +Public Class ImplementI1 + Implements I1 + ' No diagnostic + Public Property P() As Integer Implements I1.P + Get + Return 0 + End Get + Set + End Set + End Property + Public Overridable Property P2() As Integer + Get + Return 0 + End Get + Set + End Set + End Property +End Class + +Public Class Derives + Inherits ImplementI1 + ' No diagnostic + Public Overrides Property P2() As Integer + Get + Return 0 + End Get + Set + End Set + End Property +End Class"); } [Fact] public async Task CA1707_ForEvents_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class DoesNotMatter - Public Event PublicE1_ As System.EventHandler + Public Event {|#0:PublicE1_|} As System.EventHandler Private Event PrivateE2_ As System.EventHandler ' No diagnostic Friend Event InternalE3_ As System.EventHandler ' No diagnostic - Protected Event ProtectedE4_ As System.EventHandler + Protected Event {|#1:ProtectedE4_|} As System.EventHandler End Class Public Interface I1 - Event E_ As System.EventHandler + Event {|#2:E_|} As System.EventHandler End Interface Public Class ImplementI1 Implements I1 ' No diagnostic Public Event E_ As System.EventHandler Implements I1.E_ - Public Event E2_ As System.EventHandler + Public Event {|#3:E2_|} As System.EventHandler End Class Public Class Derives Inherits ImplementI1 + + 'Public Shadows Event E2_ As System.EventHandler ' Currently not renamed due to https://github.com/dotnet/roslyn/issues/46663 +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("DoesNotMatter.PublicE1_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedE4_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("I1.E_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("ImplementI1.E2_"), +}, @" +Public Class DoesNotMatter + Public Event PublicE1 As System.EventHandler + Private Event PrivateE2_ As System.EventHandler ' No diagnostic - Public Shadows Event E2_ As System.EventHandler -End Class", - GetCA1707BasicResultAt(line: 3, column: 18, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.PublicE1_"), - GetCA1707BasicResultAt(line: 8, column: 21, symbolKind: SymbolKind.Member, identifierNames: "DoesNotMatter.ProtectedE4_"), - GetCA1707BasicResultAt(line: 12, column: 11, symbolKind: SymbolKind.Member, identifierNames: "I1.E_"), - GetCA1707BasicResultAt(line: 19, column: 18, symbolKind: SymbolKind.Member, identifierNames: "ImplementI1.E2_"), - GetCA1707BasicResultAt(line: 25, column: 26, symbolKind: SymbolKind.Member, identifierNames: "Derives.E2_")); + Friend Event InternalE3_ As System.EventHandler + ' No diagnostic + Protected Event ProtectedE4 As System.EventHandler +End Class + +Public Interface I1 + Event E As System.EventHandler +End Interface + +Public Class ImplementI1 + Implements I1 + ' No diagnostic + Public Event E As System.EventHandler Implements I1.E + Public Event E2 As System.EventHandler +End Class + +Public Class Derives + Inherits ImplementI1 + + 'Public Shadows Event E2_ As System.EventHandler ' Currently not renamed due to https://github.com/dotnet/roslyn/issues/46663 +End Class"); } [Fact] public async Task CA1707_ForDelegates_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" -Public Delegate Sub Dele(intPublic_ As Integer, stringPublic_ As String) + await VerifyVB.VerifyCodeFixAsync(@" +Public Delegate Sub Dele({|#0:intPublic_|} As Integer, {|#1:stringPublic_|} As String) ' No diagnostics Friend Delegate Sub Dele2(intInternal_ As Integer, stringInternal_ As String) -Public Delegate Function Del(Of T)(t_ As Integer) As T -", - GetCA1707BasicResultAt(2, 26, SymbolKind.DelegateParameter, "Dele", "intPublic_"), - GetCA1707BasicResultAt(2, 49, SymbolKind.DelegateParameter, "Dele", "stringPublic_"), - GetCA1707BasicResultAt(5, 36, SymbolKind.DelegateParameter, "Del(Of T)", "t_")); +Public Delegate Function Del(Of T)({|#2:t_|} As Integer) As T +", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(0).WithArguments("Dele", "intPublic_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(1).WithArguments("Dele", "stringPublic_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.DelegateParameterRule).WithLocation(2).WithArguments("Del(Of T)", "t_") +}, @" +Public Delegate Sub Dele(intPublic As Integer, stringPublic As String) +' No diagnostics +Friend Delegate Sub Dele2(intInternal_ As Integer, stringInternal_ As String) +Public Delegate Function Del(Of T)(t As Integer) As T +"); } [Fact] public async Task CA1707_ForMemberparameters_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@"Public Class DoesNotMatter - Public Sub PublicM1(int_ As Integer) + await VerifyVB.VerifyCodeFixAsync(@" +Public Class DoesNotMatter + Public Sub PublicM1({|#0:int_|} As Integer) End Sub Private Sub PrivateM2(int_ As Integer) End Sub @@ -837,12 +1331,12 @@ End Sub Friend Sub InternalM3(int_ As Integer) End Sub ' No diagnostic - Protected Sub ProtectedM4(int_ As Integer) + Protected Sub ProtectedM4({|#1:int_|} As Integer) End Sub End Class Public Interface I - Sub M(int_ As Integer) + Sub M({|#2:int_|} As Integer) End Interface Public Class implementI @@ -852,10 +1346,10 @@ End Sub End Class Public MustInherit Class Base - Public Overridable Sub M1(int_ As Integer) + Public Overridable Sub M1({|#3:int_|} As Integer) End Sub - Public MustOverride Sub M2(int_ As Integer) + Public MustOverride Sub M2({|#4:int_|} As Integer) End Class Public Class Der @@ -867,43 +1361,90 @@ End Sub Public Overrides Sub M1(int_ As Integer) MyBase.M1(int_) End Sub -End Class", - GetCA1707BasicResultAt(2, 25, SymbolKind.MemberParameter, "DoesNotMatter.PublicM1(Integer)", "int_"), - GetCA1707BasicResultAt(10, 31, SymbolKind.MemberParameter, "DoesNotMatter.ProtectedM4(Integer)", "int_"), - GetCA1707BasicResultAt(15, 11, SymbolKind.MemberParameter, "I.M(Integer)", "int_"), - GetCA1707BasicResultAt(25, 31, SymbolKind.MemberParameter, "Base.M1(Integer)", "int_"), - GetCA1707BasicResultAt(28, 32, SymbolKind.MemberParameter, "Base.M2(Integer)", "int_")); +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(0).WithArguments("DoesNotMatter.PublicM1(Integer)", "int_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(1).WithArguments("DoesNotMatter.ProtectedM4(Integer)", "int_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(2).WithArguments("I.M(Integer)", "int_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(3).WithArguments("Base.M1(Integer)", "int_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberParameterRule).WithLocation(4).WithArguments("Base.M2(Integer)", "int_") +}, @" +Public Class DoesNotMatter + Public Sub PublicM1(int As Integer) + End Sub + Private Sub PrivateM2(int_ As Integer) + End Sub + ' No diagnostic + Friend Sub InternalM3(int_ As Integer) + End Sub + ' No diagnostic + Protected Sub ProtectedM4(int As Integer) + End Sub +End Class + +Public Interface I + Sub M(int As Integer) +End Interface + +Public Class implementI + Implements I + Private Sub I_M(int_ As Integer) Implements I.M + End Sub +End Class + +Public MustInherit Class Base + Public Overridable Sub M1(int As Integer) + End Sub + + Public MustOverride Sub M2(int As Integer) +End Class + +Public Class Der + Inherits Base + Public Overrides Sub M2(int_ As Integer) + Throw New System.NotImplementedException() + End Sub + + Public Overrides Sub M1(int_ As Integer) + MyBase.M1(int_) + End Sub +End Class"); } [Fact] public async Task CA1707_ForTypeTypeParameters_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" -Public Class DoesNotMatter(Of T_) + await VerifyVB.VerifyCodeFixAsync(@" +Public Class DoesNotMatter(Of {|#0:T_|}) End Class Class NoDiag(Of U_) End Class", - GetCA1707BasicResultAt(2, 31, SymbolKind.TypeTypeParameter, "DoesNotMatter(Of T_)", "T_")); + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.TypeTypeParameterRule).WithLocation(0).WithArguments("DoesNotMatter(Of T_)", "T_"), @" +Public Class DoesNotMatter(Of T) +End Class + +Class NoDiag(Of U_) +End Class"); } [Fact] public async Task CA1707_ForMemberTypeParameters_VisualBasic() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Public Class DoesNotMatter22 - Public Sub PublicM1(Of T1_)() + Public Sub PublicM1(Of {|#0:T1_|})() End Sub Private Sub PrivateM2(Of U_)() End Sub Friend Sub InternalM3(Of W_)() End Sub - Protected Sub ProtectedM4(Of D_)() + Protected Sub ProtectedM4(Of {|#1:D_|})() End Sub End Class Public Interface I - Sub M(Of T_)() + Sub M(Of {|#2:T_|})() End Interface Public Class implementI @@ -914,10 +1455,10 @@ End Sub End Class Public MustInherit Class Base - Public Overridable Sub M1(Of T_)() + Public Overridable Sub M1(Of {|#3:T_|})() End Sub - Public MustOverride Sub M2(Of U_)() + Public MustOverride Sub M2(Of {|#4:U_|})() End Class Public Class Der @@ -929,12 +1470,53 @@ End Sub Public Overrides Sub M1(Of T_)() MyBase.M1(Of T_)() End Sub -End Class", - GetCA1707BasicResultAt(3, 28, SymbolKind.MethodTypeParameter, "DoesNotMatter22.PublicM1(Of T1_)()", "T1_"), - GetCA1707BasicResultAt(9, 34, SymbolKind.MethodTypeParameter, "DoesNotMatter22.ProtectedM4(Of D_)()", "D_"), - GetCA1707BasicResultAt(14, 14, SymbolKind.MethodTypeParameter, "I.M(Of T_)()", "T_"), - GetCA1707BasicResultAt(25, 34, SymbolKind.MethodTypeParameter, "Base.M1(Of T_)()", "T_"), - GetCA1707BasicResultAt(28, 35, SymbolKind.MethodTypeParameter, "Base.M2(Of U_)()", "U_")); +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(0).WithArguments("DoesNotMatter22.PublicM1(Of T1_)()", "T1_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(1).WithArguments("DoesNotMatter22.ProtectedM4(Of D_)()", "D_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(2).WithArguments("I.M(Of T_)()", "T_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(3).WithArguments("Base.M1(Of T_)()", "T_"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MethodTypeParameterRule).WithLocation(4).WithArguments("Base.M2(Of U_)()", "U_") +}, @" +Public Class DoesNotMatter22 + Public Sub PublicM1(Of T1)() + End Sub + Private Sub PrivateM2(Of U_)() + End Sub + Friend Sub InternalM3(Of W_)() + End Sub + Protected Sub ProtectedM4(Of D)() + End Sub +End Class + +Public Interface I + Sub M(Of T)() +End Interface + +Public Class implementI + Implements I + Public Sub M(Of U_)() Implements I.M + Throw New System.NotImplementedException() + End Sub +End Class + +Public MustInherit Class Base + Public Overridable Sub M1(Of T)() + End Sub + + Public MustOverride Sub M2(Of U)() +End Class + +Public Class Der + Inherits Base + Public Overrides Sub M2(Of U_)() + Throw New System.NotImplementedException() + End Sub + + Public Overrides Sub M1(Of T_)() + MyBase.M1(Of T_)() + End Sub +End Class"); } [Fact, WorkItem(947, "https://github.com/dotnet/roslyn-analyzers/issues/947")] @@ -981,7 +1563,7 @@ End Class [Fact, WorkItem(3121, "https://github.com/dotnet/roslyn-analyzers/issues/3121")] public async Task CA1707_VisualBasic_GlobalAsaxSpecialMethods() { - await VerifyVB.VerifyAnalyzerAsync(@" + await VerifyVB.VerifyCodeFixAsync(@" Imports System Namespace System.Web @@ -1021,6 +1603,54 @@ End Sub End Class Public Class InvalidContext + Protected Sub {|#0:Application_AuthenticateRequest|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#1:Application_BeginRequest|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#2:Application_End|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#3:Application_EndRequest|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#4:Application_Error|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#5:Application_Init|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#6:Application_Start|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#7:Session_End|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub {|#8:Session_Start|}(ByVal sender As Object, ByVal e As EventArgs) + End Sub +End Class", new[] +{ + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(0).WithArguments("InvalidContext.Application_AuthenticateRequest(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(1).WithArguments("InvalidContext.Application_BeginRequest(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(2).WithArguments("InvalidContext.Application_End(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(3).WithArguments("InvalidContext.Application_EndRequest(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(4).WithArguments("InvalidContext.Application_Error(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(5).WithArguments("InvalidContext.Application_Init(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(6).WithArguments("InvalidContext.Application_Start(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(7).WithArguments("InvalidContext.Session_End(Object, System.EventArgs)"), + VerifyVB.Diagnostic(IdentifiersShouldNotContainUnderscoresAnalyzer.MemberRule).WithLocation(8).WithArguments("InvalidContext.Session_Start(Object, System.EventArgs)") +}, @" +Imports System + +Namespace System.Web + Public Class HttpApplication + End Class +End Namespace + +Public Class ValidContext + Inherits System.Web.HttpApplication + Protected Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) End Sub @@ -1047,16 +1677,36 @@ End Sub Protected Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) End Sub -End Class", - GetCA1707BasicResultAt(41, 19, SymbolKind.Member, "InvalidContext.Application_AuthenticateRequest(Object, System.EventArgs)"), - GetCA1707BasicResultAt(44, 19, SymbolKind.Member, "InvalidContext.Application_BeginRequest(Object, System.EventArgs)"), - GetCA1707BasicResultAt(47, 19, SymbolKind.Member, "InvalidContext.Application_End(Object, System.EventArgs)"), - GetCA1707BasicResultAt(50, 19, SymbolKind.Member, "InvalidContext.Application_EndRequest(Object, System.EventArgs)"), - GetCA1707BasicResultAt(53, 19, SymbolKind.Member, "InvalidContext.Application_Error(Object, System.EventArgs)"), - GetCA1707BasicResultAt(56, 19, SymbolKind.Member, "InvalidContext.Application_Init(Object, System.EventArgs)"), - GetCA1707BasicResultAt(59, 19, SymbolKind.Member, "InvalidContext.Application_Start(Object, System.EventArgs)"), - GetCA1707BasicResultAt(62, 19, SymbolKind.Member, "InvalidContext.Session_End(Object, System.EventArgs)"), - GetCA1707BasicResultAt(65, 19, SymbolKind.Member, "InvalidContext.Session_Start(Object, System.EventArgs)")); +End Class + +Public Class InvalidContext + Protected Sub ApplicationAuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationBeginRequest(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationEnd(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationEndRequest(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationError(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationInit(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub ApplicationStart(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub SessionEnd(ByVal sender As Object, ByVal e As EventArgs) + End Sub + + Protected Sub SessionStart(ByVal sender As Object, ByVal e As EventArgs) + End Sub +End Class"); } #endregion @@ -1102,4 +1752,4 @@ private enum SymbolKind } #endregion } -} \ No newline at end of file +} diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicIdentifiersShouldNotContainUnderscores.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicIdentifiersShouldNotContainUnderscores.Fixer.vb index cf15a20324..07daffcd71 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicIdentifiersShouldNotContainUnderscores.Fixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/BasicIdentifiersShouldNotContainUnderscores.Fixer.vb @@ -4,6 +4,7 @@ Imports System.Composition Imports Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeFixes +Imports Microsoft.CodeAnalysis.VisualBasic Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines ''' @@ -13,5 +14,25 @@ Namespace Microsoft.CodeQuality.VisualBasic.Analyzers.ApiDesignGuidelines Public NotInheritable Class BasicIdentifiersShouldNotContainUnderscoresFixer Inherits IdentifiersShouldNotContainUnderscoresFixer + Protected Overrides Function GetNewName(name As String) As String + Dim result = RemoveUnderscores(name) + If result.Length = 0 Then + Return String.Empty + End If + + If Not SyntaxFacts.IsValidIdentifier(result) Then + Return $"[{result}]" + End If + + Return result + End Function + + Protected Overrides Function GetDeclarationNode(node As SyntaxNode) As SyntaxNode + If node.IsKind(SyntaxKind.IdentifierName) Then + Return node.Parent + Else + Return node + End If + End Function End Class End Namespace From 3d4966ed1d00e6735fa3655b10035f24fecc7b97 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Sun, 20 Dec 2020 19:43:22 +0200 Subject: [PATCH 2/3] Update auto-generated files --- src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index a043dab04b..1b34b87b49 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -813,7 +813,7 @@ By convention, identifier names do not contain the underscore (_) character. Thi |Category|Naming| |Enabled|True| |Severity|Hidden| -|CodeFix|False| +|CodeFix|True| --- ## [CA1708](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1708): Identifiers should differ by more than case From 7b559cd21e8473c8e2315803e7f12620438c75a9 Mon Sep 17 00:00:00 2001 From: Youssef Victor <31348972+Youssef1313@users.noreply.github.com> Date: Mon, 21 Dec 2020 18:59:22 +0200 Subject: [PATCH 3/3] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Amaury Levé --- .../CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs | 2 ++ .../IdentifiersShouldNotContainUnderscores.Fixer.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs index 08f581228e..83b9a4f2b1 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/CSharpIdentifiersShouldNotContainUnderscores.Fixer.cs @@ -18,7 +18,9 @@ protected override string GetNewName(string name) { string result = RemoveUnderscores(name); if (result.Length == 0) + { return string.Empty; + } if (!SyntaxFacts.IsValidIdentifier(result)) { diff --git a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs index eef21f8070..68ab60cad4 100644 --- a/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/ApiDesignGuidelines/IdentifiersShouldNotContainUnderscores.Fixer.cs @@ -76,9 +76,11 @@ protected static string RemoveUnderscores(string name) isPreviousUnderscore = true; continue; } + builder.Append(isPreviousUnderscore ? char.ToUpper(c, CultureInfo.InvariantCulture) : c); isPreviousUnderscore = false; } + return builder.ToString(); }