Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CA1806 to allow user defined methods #3483

Merged
merged 7 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion docs/Analyzer Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,26 @@ Option Values: Boolean values

Default Value: `false`

Example: `dotnet_code_quality.CA1303.use_naming_heuristic = true`
Example: `dotnet_code_quality.CA1303.use_naming_heuristic = true`

### Additional use results methods
Option Name: `additional_use_results_methods`

Configurable Rules: [CA1806](https://docs.microsoft.com/en-us/visualstudio/code-quality/CA1806)

Option Values: Names of additional methods (separated by '|') for CA1806.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to also allow types? Same question for namespaces? IMO types could make sense but I fail to see any point for namespaces.

Allowed method name formats:
1. Method name only (includes all methods with the name, regardless of the containing type or namespace)
2. Fully qualified names in the symbol's documentation ID format: https://github.com/dotnet/csharplang/blob/master/spec/documentation-comments.md#id-string-format
with an optional "M:" prefix.

Default Value: None

Examples:

| Option Value | Summary |
| --- | --- |
|`dotnet_code_quality.CA1806.additional_use_results_methods = MyMethod` | Matches all methods named 'MyMethod' in the compilation
|`dotnet_code_quality.CA1806.additional_use_results_methods = MyMethod1\|MyMethod2` | Matches all methods named either 'MyMethod1' or 'MyMethod2' in the compilation
|`dotnet_code_quality.CA1806.additional_use_results_methods = M:NS.MyType.MyMethod(ParamType)` | Matches specific method 'MyMethod' with given fully qualified signature
|`dotnet_code_quality.CA1806.additional_use_results_methods = M:NS1.MyType1.MyMethod1(ParamType)\|M:NS2.MyType2.MyMethod2(ParamType)` | Matches specific methods 'MyMethod1' and 'MyMethod2' with respective fully qualified signature
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public sealed class DoNotIgnoreMethodResultsAnalyzer : DiagnosticAnalyzer
private static readonly LocalizableString s_localizableMessagePureMethod = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.DoNotIgnoreMethodResultsMessagePureMethod), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources));
private static readonly LocalizableString s_localizableMessageTryParse = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.DoNotIgnoreMethodResultsMessageTryParse), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources));
private static readonly LocalizableString s_localizableMessageLinqMethod = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.DoNotIgnoreMethodResultsMessageLinqMethod), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources));
private static readonly LocalizableString s_localizableMessageUserDefinedMethod = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.DoNotIgnoreMethodResultsMessageUserDefinedMethod), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources));
private static readonly LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(MicrosoftCodeQualityAnalyzersResources.DoNotIgnoreMethodResultsDescription), MicrosoftCodeQualityAnalyzersResources.ResourceManager, typeof(MicrosoftCodeQualityAnalyzersResources));

internal static DiagnosticDescriptor ObjectCreationRule = DiagnosticDescriptorHelper.Create(RuleId,
Expand Down Expand Up @@ -126,6 +127,15 @@ public sealed class DoNotIgnoreMethodResultsAnalyzer : DiagnosticAnalyzer
isPortedFxCopRule: true,
isDataflowRule: false);

internal static DiagnosticDescriptor UserDefinedMethodRule = DiagnosticDescriptorHelper.Create(RuleId,
s_localizableTitle,
s_localizableMessageUserDefinedMethod,
DiagnosticCategory.Performance,
RuleLevel.IdeSuggestion,
description: s_localizableDescription,
isPortedFxCopRule: true,
isDataflowRule: false);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ObjectCreationRule, StringCreationRule, HResultOrErrorCodeRule, TryParseRule, PureMethodRule);

public override void Initialize(AnalysisContext analysisContext)
Expand All @@ -150,6 +160,9 @@ public override void Initialize(AnalysisContext analysisContext)
osContext.RegisterOperationAction(opContext =>
{
IOperation expression = ((IExpressionStatementOperation)opContext.Operation).Operation;

var userDefinedMethods = compilationContext.Options.GetAdditionalUseResultsMethodsOption(UserDefinedMethodRule, expression.Syntax.SyntaxTree, compilationContext.Compilation, compilationContext.CancellationToken);

DiagnosticDescriptor? rule = null;
string? targetMethodName = null;
switch (expression.Kind)
Expand Down Expand Up @@ -191,6 +204,10 @@ public override void Initialize(AnalysisContext analysisContext)
{
rule = LinqMethodRule;
}
else if (userDefinedMethods.Contains(targetMethod.OriginalDefinition))
{
rule = UserDefinedMethodRule;
}

targetMethodName = targetMethod.Name;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1436,4 +1436,7 @@
<data name="EventsShouldNotHaveBeforeOrAfterPrefixTitle" xml:space="preserve">
<value>Events should not have 'Before' or 'After' prefix</value>
</data>
<data name="DoNotIgnoreMethodResultsMessageUserDefinedMethod" xml:space="preserve">
<value>'{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.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">{0} volá {1}, ale nepoužívá hodnotu, kterou tato metoda vrací. O metodách Linq se ví, že nemají vedlejší účinky. Použijte výsledek v podmíněném příkazu, přiřaďte výsledek proměnné nebo ho předejte jako argument jiné metodě.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">Tato role předpokládá, že člen výčtu s názvem, který obsahuje reserved, se v tuto chvíli nepoužívá, ale představuje zástupný symbol, který se má přejmenovat nebo odebrat v budoucí verzi. Přejmenování nebo odebrání členu je změna způsobující chybu.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">"{0}" ruft "{1}" auf, verwendet jedoch nicht den von der Methode zurückgegebenen Wert. Linq-Methoden sind bekannt dafür, dass sie keine Nebeneffekte haben. Verwenden Sie das Ergebnis in einer Bedingungsanweisung, weisen Sie das Ergebnis einer Variablen zu, oder übergeben Sie es als Argument an eine andere Methode.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">Diese Regel setzt voraus, dass ein Enumerationsmember mit "reserved" im Namen aktuell nicht verwendet wird, aber als Platzhalter fungiert, der in einer zukünftigen Version umbenannt oder entfernt werden soll. Das Umbenennen oder Entfernen eines Members ist ein Breaking Change.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">"{0}" llama a "{1}", pero no usa el valor que el método devuelve. Los métodos LINQ son conocidos por no tener efectos secundarios. Use el resultado en una instrucción condicional, asigne el resultado a una variable o páselo como argumento a otro método.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">Esta regla asume que un miembro de enumeración con un nombre que contiene "reservado" no se usa actualmente, sino que es un marcador de posición que se cambiará de nombre o se quitará en una versión futura. Quitar un miembro o cambiarlo de nombre es un cambio importante.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">'{0}' appelle '{1}' mais n'utilise pas la valeur retournée par la méthode. Les méthodes Linq sont connues pour ne pas avoir d'effets secondaires. Utilisez le résultat dans une instruction conditionnelle, assignez-le à une variable ou passez-le en tant qu'argument à une autre méthode.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">Cette règle part du principe qu'un membre d'énumération dont le nom contient "reserved" n'est pas utilisé mais qu'il représente un espace réservé à renommer ou à supprimer dans une version future. Le renommage ou la suppression d'un membre est un changement cassant.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">'{0}' chiama '{1}' ma non usa il valore restituito dal metodo. È noto che i metodi Linq non presentino effetti collaterali. Usare il risultato in un'istruzione condizionale, assegnare il risultato a una variabile o passarlo come argomento a un altro metodo.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">Questa regola presuppone che un membro di enumerazione il cui nome contiene la parola "reserved" non sia attualmente usato, ma che sia un segnaposto da rinominare o rimuovere in una versione futura. La ridenominazione o la rimozione di un membro è una modifica che causa un'interruzione.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">'{0}' は '{1}' を呼び出しますが、メソッドから返される値を使用していません。Linq メソッドでは副作用が発生しないことがわかっています。条件ステートメントで結果を使用するか、結果を変数に割り当てるか、引数として他のメソッドに渡してください。</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">この規則では、名前に "reserved" が含まれる列挙型メンバーは現在使用されていないことが前提とされていますが、そのようなものは、将来のバージョンで名前変更または削除されるプレースホルダーとなります。メンバーの名前変更または削除は、破壊的変更です。</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">'{0}'이(가) '{1}'을(를) 호출하지만 메서드에서 반환된 값을 사용하지 않습니다. LINQ 메서드는 부작용이 없는 것으로 알려져 있습니다. 결과를 조건문에 사용하거나, 변수에 할당하거나, 다른 메서드에 인수로 전달하세요.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">이 규칙에서 이름에 "reserved"가 포함된 열거형 멤버는 현재 사용되고 있지 않으며 이후 버전에서 이름을 바꾸거나 제거할 자리 표시자라고 가정합니다. 멤버 제거 또는 이름 바꾸기는 호환성이 손상되는 변경 내용입니다.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@
<target state="translated">Element „{0}” wywołuje element „{1}”, ale nie używa wartości zwracanej przez metodę. Metody linq mają efekty uboczne. Użyj wyniku w instrukcji warunkowej, przypisz wynik do zmiennej lub przekaż go jako argument do innej metody.</target>
<note />
</trans-unit>
<trans-unit id="DoNotIgnoreMethodResultsMessageUserDefinedMethod">
<source>'{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.</source>
<target state="new">'{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.</target>
<note />
</trans-unit>
<trans-unit id="DoNotNameEnumValuesReservedDescription">
<source>This rule assumes that an enumeration member that has a name that contains "reserved" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.</source>
<target state="translated">W tej regule przyjęto założenie, że element członkowski wyliczenia, który ma nazwę zawierającą wyraz „reserved”, nie jest obecnie używany, ale jest symbolem zastępczym, którego nazwa może zostać zmieniona lub usunięta w przyszłej wersji. Zmiana nazwy lub usunięcie elementu członkowskiego jest zmianą powodującą niezgodność.</target>
Expand Down
Loading