diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
index 01eac786fd..f5c67ef4e1 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx
@@ -290,6 +290,9 @@
Provide correct arguments to formatting methods
+
+ The format argument is not a valid format string
+
Test for NaN correctly
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
index b18767a9fc..bfb858e37a 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using Analyzer.Utilities;
using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis;
@@ -23,7 +24,7 @@ public class ProvideCorrectArgumentsToFormattingMethodsAnalyzer : DiagnosticAnal
{
internal const string RuleId = "CA2241";
- internal static readonly DiagnosticDescriptor Rule = DiagnosticDescriptorHelper.Create(
+ internal static readonly DiagnosticDescriptor ArgumentCountRule = DiagnosticDescriptorHelper.Create(
RuleId,
CreateLocalizableResourceString(nameof(ProvideCorrectArgumentsToFormattingMethodsTitle)),
CreateLocalizableResourceString(nameof(ProvideCorrectArgumentsToFormattingMethodsMessage)),
@@ -33,7 +34,18 @@ public class ProvideCorrectArgumentsToFormattingMethodsAnalyzer : DiagnosticAnal
isPortedFxCopRule: true,
isDataflowRule: false);
- public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
+ internal static readonly DiagnosticDescriptor InvalidFormatRule = DiagnosticDescriptorHelper.Create(
+ RuleId,
+ CreateLocalizableResourceString(nameof(ProvideCorrectArgumentsToFormattingMethodsTitle)),
+ CreateLocalizableResourceString(nameof(ProvideCorrectArgumentsToFormattingMethodsInvalidFormatMessage)),
+ DiagnosticCategory.Usage,
+ RuleLevel.BuildWarningCandidate,
+ description: CreateLocalizableResourceString(nameof(ProvideCorrectArgumentsToFormattingMethodsDescription)),
+ isPortedFxCopRule: true,
+ isDataflowRule: false);
+
+ public override ImmutableArray SupportedDiagnostics { get; } =
+ ImmutableArray.Create(ArgumentCountRule, InvalidFormatRule);
public override void Initialize(AnalysisContext context)
{
@@ -65,6 +77,13 @@ public override void Initialize(AnalysisContext context)
int expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat);
+ if (expectedStringFormatArgumentCount < 0)
+ {
+ // Malformed format specification
+ operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(InvalidFormatRule));
+ return;
+ }
+
// explicit parameter case
if (info.ExpectedStringFormatArgumentCount >= 0)
{
@@ -77,11 +96,16 @@ public override void Initialize(AnalysisContext context)
if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount)
{
- operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule));
+ operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(ArgumentCountRule));
}
return;
}
+ else if (info.ExpectedStringFormatArgumentCount == -2)
+ {
+ // Not a formatting method, we only checked the format specification.
+ return;
+ }
// ensure argument is an array
IArgumentOperation paramsArgument = invocation.Arguments[info.FormatStringIndex + 1];
@@ -111,7 +135,7 @@ public override void Initialize(AnalysisContext context)
int actualArgumentCount = initializer.ElementValues.Length;
if (actualArgumentCount != expectedStringFormatArgumentCount)
{
- operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule));
+ operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(ArgumentCountRule));
}
}, OperationKind.Invocation);
});
@@ -308,7 +332,7 @@ private static int GetFormattingArguments(string format)
} // end of main loop
- return uniqueNumbers.Count;
+ return uniqueNumbers.Count == 0 ? 0 : uniqueNumbers.Max() + 1;
}
private class StringFormatInfo
@@ -352,7 +376,7 @@ public StringFormatInfo(Compilation compilation)
}
// Check if this the underlying method is user configured string formatting method.
- var additionalStringFormatMethodsOption = context.Options.GetAdditionalStringFormattingMethodsOption(Rule, context.Operation.Syntax.SyntaxTree, context.Compilation);
+ var additionalStringFormatMethodsOption = context.Options.GetAdditionalStringFormattingMethodsOption(ArgumentCountRule, context.Operation.Syntax.SyntaxTree, context.Compilation);
if (additionalStringFormatMethodsOption.Contains(method.OriginalDefinition) &&
TryGetFormatInfoByParameterName(method, out info))
{
@@ -362,7 +386,7 @@ public StringFormatInfo(Compilation compilation)
// Check if the user configured automatic determination of formatting methods.
// If so, check if the method called has a 'string format' parameter followed by an params array.
var determineAdditionalStringFormattingMethodsAutomatically = context.Options.GetBoolOptionValue(EditorConfigOptionNames.TryDetermineAdditionalStringFormattingMethodsAutomatically,
- Rule, context.Operation.Syntax.SyntaxTree, context.Compilation, defaultValue: false);
+ ArgumentCountRule, context.Operation.Syntax.SyntaxTree, context.Compilation, defaultValue: false);
if (determineAdditionalStringFormattingMethodsAutomatically &&
TryGetFormatInfoByParameterName(method, out info) &&
info.ExpectedStringFormatArgumentCount == -1)
@@ -424,6 +448,13 @@ private bool TryGetFormatInfo(IMethodSymbol method, int formatIndex, [NotNullWhe
private static int GetExpectedNumberOfArguments(ImmutableArray parameters, int formatIndex)
{
+ if (formatIndex == parameters.Length - 1)
+ {
+ // format specification is the last parameter (e.g. CompositeFormat.Parse)
+ // this is therefore not a formatting method.
+ return -2;
+ }
+
// check params
IParameterSymbol nextParameter = parameters[formatIndex + 1];
if (nextParameter.IsParams)
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
index c4f98859c8..137ae94cef 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf
@@ -2288,6 +2288,11 @@ Obecné přetypování (IL unbox.any) používané sekvencí vrácenou metodou E
Argument formátu, který se předává do System.String.Format, neobsahuje položku formátování, která odpovídá jednotlivým argumentům objektů, nebo naopak.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsPoskytněte metodám formátování správné argumenty
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
index 62b16ed7d7..4f473ce27b 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf
@@ -2288,6 +2288,11 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type
Das an "System.String.Format" übergebene Formatargument enthält kein Formatelement, das den einzelnen Objektargumenten entspricht bzw. umgekehrt.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsGeeignete Argumente für Formatierungsmethoden angeben
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
index d21492215c..60d7531526 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf
@@ -2288,6 +2288,11 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip
El argumento de cadena format pasado a System.String.Format no contiene un elemento de formato que corresponda a cada argumento de objeto o viceversa.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsProporcionar argumentos correctos para los métodos de formato
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
index c14f18c29d..c6b0b30652 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf
@@ -2288,6 +2288,11 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en
L'argument de mise en forme passé à System.String.Format ne contient aucun élément de mise en forme pour chaque argument d'objet correspondant, ou vice versa.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsIndiquer le nombre correct d'arguments dans les méthodes de mise en forme
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
index 7bd9111cf7..21d943a5f7 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf
@@ -2288,6 +2288,11 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi
L'argomento format passato a System.String.Format non contiene un elemento di formato corrispondente a ogni argomento dell'oggetto o viceversa.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsFornire gli argomenti corretti ai metodi di formattazione
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
index 5bc3a0ca3e..157c639229 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf
@@ -2288,6 +2288,11 @@ Enumerable.OfType<T> で使用されるジェネリック型チェック (
System.String.Format に渡される書式引数には、各オブジェクト引数に対応する書式項目が含まれていないか、各書式項目に対応するオブジェクト引数が含まれていません。
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methods書式設定メソッドに正しい引数を指定します
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
index 70a0a87e6d..c51c4b7520 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf
@@ -2288,6 +2288,11 @@ Enumerable.OfType<T>에서 사용하는 제네릭 형식 검사(C# 'is'
System.String.Format으로 전달된 format 인수에 각 개체 인수에 해당하는 format 항목이 포함되지 않으며 그 반대의 경우도 마찬가지입니다.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methods서식 지정 메서드에 올바른 인수를 제공하세요.
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
index 39b613af0b..6716383b08 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf
@@ -2288,6 +2288,11 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr
Argument formatu przekazywany do metody System.String.Format nie zawiera elementu formatu odpowiadającego każdemu argumentowi obiektu lub odwrotnie.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsOkreśl poprawne argumenty dla metod formatujących
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
index 5f63fca477..1158c1feea 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf
@@ -2288,6 +2288,11 @@ Ampliação e conversões definidas pelo usuário não são compatíveis com tip
O argumento de formato passado para System.String.Format não contém um item de formato correspondente a cada argumento de objeto ou vice-versa.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsFornecer os argumentos corretos para métodos de formatação
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
index 4bef823371..2fc84e2559 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf
@@ -2288,6 +2288,11 @@ Widening and user defined conversions are not supported with generic types.Передаваемый в System.String.Format аргумент формата не содержит элемент формата, соответствующий каждому из аргументов объекта, или наоборот.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsЗадайте правильные аргументы для методов форматирования
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
index b68be988c9..dc915b4ce8 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf
@@ -2288,6 +2288,11 @@ Genel türlerde genişletme ve kullanıcı tanımlı dönüştürmeler desteklen
System.String.Format’a geçirilen biçim bağımsız değişkeni, her nesne bağımsız değişkenine karşılık gelen bir biçim öğesi içermiyor ve tersi için de aynısı geçerli.
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methodsBiçimlendirme yöntemlerine doğru bağımsız değişkenleri sağlayın
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
index a7e56d5a10..7c3ee317d2 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf
@@ -2288,6 +2288,11 @@ Enumerable.OfType<T> 使用的泛型类型检查 (C# 'is' operator/IL 'isi
传递到 System.String.Format 的 format 参数不包含与各对象参数相对应的格式项,反之亦然。
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methods为格式化方法提供正确的参数
diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
index c28ef39f4f..856cc16550 100644
--- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
+++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf
@@ -2288,6 +2288,11 @@ Enumerable.OfType<T> 使用的一般型別檢查 (C# 'is' operator/IL 'isi
傳遞給 System.String.Format 的格式化引數,並未包含與每個物件引數相對應的格式項目,反之亦然。
+
+ The format argument is not a valid format string
+ The format argument is not a valid format string
+
+ Provide correct arguments to formatting methods為格式化方法提供正確的引數
diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md
index eb030b9cc5..42df726b08 100644
--- a/src/NetAnalyzers/RulesMissingDocumentation.md
+++ b/src/NetAnalyzers/RulesMissingDocumentation.md
@@ -13,6 +13,5 @@ CA1863 | | Use char overload |
CA1866 | | Use char overload |
CA1867 | | Use char overload |
-CA1869 | | Cache and reuse 'JsonSerializerOptions' instances |
CA2021 | | Do not call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types |
CA2261 | | Do not use ConfigureAwaitOptions.SuppressThrowing with Task\ |
diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs
index 19d10ea590..ee635c49b2 100644
--- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs
+++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
@@ -118,6 +119,7 @@ void Method()
var c = String.Format(""{0} {1} {2}"", 1, 2, 3);
var d = String.Format(""{0} {1} {2} {3}"", 1, 2, 3, 4);
var e = String.Format(""{0} {1} {2} {0}"", 1, 2, 3);
+ var f = String.Format(""{0} {0} {0} {0}"", 1);
Console.Write(""{0}"", 1);
Console.Write(""{0} {1}"", 1, 2);
@@ -125,6 +127,7 @@ void Method()
Console.Write(""{0} {1} {2} {3}"", 1, 2, 3, 4);
Console.Write(""{0} {1} {2} {3} {4}"", 1, 2, 3, 4, 5);
Console.Write(""{0} {1} {2} {3} {0}"", 1, 2, 3, 4);
+ Console.Write(""{0} {0} {0} {0} {0}"", 1);
Console.WriteLine(""{0}"", 1);
Console.WriteLine(""{0} {1}"", 1, 2);
@@ -132,11 +135,50 @@ void Method()
Console.WriteLine(""{0} {1} {2} {3}"", 1, 2, 3, 4);
Console.WriteLine(""{0} {1} {2} {3} {4}"", 1, 2, 3, 4, 5);
Console.WriteLine(""{0} {1} {2} {3} {0}"", 1, 2, 3, 4);
+ Console.WriteLine(""{0} {0} {0} {0} {0}"", 1);
}
}
");
}
+ [Fact]
+ public async Task CA2241CSharpDifferentDiagnosticsAsync()
+ {
+ await VerifyCS.VerifyAnalyzerAsync(@"
+using System;
+
+public class C
+{
+ void Method()
+ {
+ var a = String.Format(""{1}"", 1);
+ var b = String.Format(""{0} {1}"", 1, 2);
+ var c = String.Format(""{0} {1}"", 1, 2, 3);
+ var d = String.Format(""{0} {1} {2"", 1, 2, 3);
+
+ Console.Write(""{1}"", 1);
+ Console.Write(""{0} {1}"", 1, 2);
+ Console.Write(""{0} {1}"", 1, 2, 3);
+ Console.Write(""{0} {1} {2"", 1, 2, 3);
+
+ Console.WriteLine(""{1}"", 1);
+ Console.WriteLine(""{0} {1}"", 1, 2);
+ Console.WriteLine(""{0} {1}"", 1, 2, 3);
+ Console.WriteLine(""{0} {1} {2"", 1, 2, 3);
+ }
+}
+",
+ GetCSharpResultAt(8, 17, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(10, 17, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(11, 17, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.InvalidFormatRule),
+ GetCSharpResultAt(13, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(15, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(16, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.InvalidFormatRule),
+ GetCSharpResultAt(18, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(20, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule),
+ GetCSharpResultAt(21, 9, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.InvalidFormatRule));
+ }
+
[Fact]
public async Task CA2241CSharpExplicitObjectArraySupportedAsync()
{
@@ -573,17 +615,54 @@ End Class"
await basicTest.RunAsync();
}
+ [Fact]
+ [WorkItem(90357, "https://github.com/dotnet/runtime/issues/90357")]
+ public async Task CA2241CSharpMethodWithNoPossibleArgumentsOnlyChecksFormat()
+ {
+ var csharpTest = new VerifyCS.Test
+ {
+ TestState =
+ {
+ Sources =
+ {
+ @"
+using System.Diagnostics.CodeAnalysis;
+
+class Test
+{
+ public static int Parse([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format) => -1;
+
+ void M1(string param)
+ {
+ var a = Parse(""{0} {1}"");
+ var b = Parse(""{0 {1}"");
+ }
+}"
+ },
+ ReferenceAssemblies = ReferenceAssemblies.Net.Net70,
+ }
+ };
+
+ csharpTest.ExpectedDiagnostics.Add(
+ GetCSharpResultAt(11, 17, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.InvalidFormatRule));
+
+ await csharpTest.RunAsync();
+ }
+
#endregion
private static DiagnosticResult GetCSharpResultAt(int line, int column)
+ => GetCSharpResultAt(line, column, ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule);
+
+ private static DiagnosticResult GetCSharpResultAt(int line, int column, DiagnosticDescriptor descriptor)
#pragma warning disable RS0030 // Do not use banned APIs
- => VerifyCS.Diagnostic()
+ => VerifyCS.Diagnostic(descriptor)
.WithLocation(line, column);
#pragma warning restore RS0030 // Do not use banned APIs
private static DiagnosticResult GetBasicResultAt(int line, int column)
#pragma warning disable RS0030 // Do not use banned APIs
- => VerifyVB.Diagnostic()
+ => VerifyVB.Diagnostic(ProvideCorrectArgumentsToFormattingMethodsAnalyzer.ArgumentCountRule)
.WithLocation(line, column);
#pragma warning restore RS0030 // Do not use banned APIs
}