diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx index 036574158e..a859882a55 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx @@ -1877,7 +1877,7 @@ Specify current culture - User an invariant version + Use an invariant version Using features that require runtime marshalling when runtime marshalling is disabled will result in runtime exceptions. 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 9b25a71272..a2da122dab 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Uživatel s neutrální verzí + Use an invariant version + Uživatel s neutrální verzí 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 e52f51076e..33a1ae79d1 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Verwenden Sie eine unveränderliche Version + Use an invariant version + Verwenden Sie eine unveränderliche Version 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 ad712aee28..269d1e488a 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Usuario de una versión invariable + Use an invariant version + Usuario de una versión invariable 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 c43ce919cf..c97656b4a4 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Utilisateur avec une version invariante + Use an invariant version + Utilisateur avec une version invariante 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 6b70f72fc7..200f70f095 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Utente di una versione invariante + Use an invariant version + Utente di una versione invariante 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 eee36fe58f..ebd50e022b 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - インバリアント バージョンを使用する + Use an invariant version + インバリアント バージョンを使用する 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 a91aea3a9a..ab05efe27a 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - 사용자 불변 버전 + Use an invariant version + 사용자 불변 버전 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 51eaf50372..053c699ab1 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Użyj niezmiennej wersji + Use an invariant version + Użyj niezmiennej wersji 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 621d57d0d3..6d041d8e9f 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 @@ -2753,8 +2753,8 @@ - User an invariant version - Usar uma versão invariável + Use an invariant version + Usar uma versão invariável 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 81153aba6b..f2e7d17398 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Использование инвариантной версии + Use an invariant version + Использование инвариантной версии 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 79ea866233..7b7242ad32 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf @@ -2753,8 +2753,8 @@ - User an invariant version - Sabit bir sürüm kullanın + Use an invariant version + Sabit bir sürüm kullanı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 d9d29b82fe..71b497cf1e 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 @@ -2753,8 +2753,8 @@ - User an invariant version - 用户固定版本 + Use an invariant version + 用户固定版本 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 7d87e8af53..9a92eec433 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 @@ -2753,8 +2753,8 @@ - User an invariant version - 使用者固定版本 + Use an invariant version + 使用者固定版本 diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/SpecifyCultureForToLowerAndToUpperTests.Fixer.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/SpecifyCultureForToLowerAndToUpperTests.Fixer.cs index a40bcbbf05..1726d91c9f 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/SpecifyCultureForToLowerAndToUpperTests.Fixer.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/SpecifyCultureForToLowerAndToUpperTests.Fixer.cs @@ -124,6 +124,42 @@ End Class }.RunAsync(); } + [Fact] + public async Task CA1311_FixToLowerBasicAsync_SpecifyCurrentCulture_MemberAccessSyntax() + { + var source = @" +Imports System.Globalization +Class C + Sub M() + Dim a = ""test"" + a.[|ToLower|] + a?.[|ToLower|] + Dim b = a.[|ToLower|] + Dim c = a?.[|ToLower|] + End Sub +End Class +"; + + var fixedSource = @" +Imports System.Globalization +Class C + Sub M() + Dim a = ""test"" + a.ToLower(CultureInfo.CurrentCulture) + a?.ToLower(CultureInfo.CurrentCulture) + Dim b = a.ToLower(CultureInfo.CurrentCulture) + Dim c = a?.ToLower(CultureInfo.CurrentCulture) + End Sub +End Class +"; + await new VerifyVB.Test + { + TestState = { Sources = { source } }, + FixedState = { Sources = { fixedSource } }, + CodeActionIndex = 0, + CodeActionEquivalenceKey = nameof(MicrosoftNetCoreAnalyzersResources.SpecifyCurrentCulture), + }.RunAsync(); + } [Fact] public async Task CA1311_FixToLowerBasicAsync_UseInvariantVersion() @@ -157,6 +193,42 @@ End Class }.RunAsync(); } + [Fact] + public async Task CA1311_FixToLowerBasicAsync_UseInvariantVersion_MemberAccessSyntax() + { + const string source = @" +Class C + Sub M() + Dim a = ""test"" + a.[|ToLower|] + a?.[|ToLower|] + Dim b = a.[|ToLower|] + Dim c = a?.[|ToLower|] + End Sub +End Class +"; + + const string fixedSource = @" +Class C + Sub M() + Dim a = ""test"" + a.ToLowerInvariant + a?.ToLowerInvariant + Dim b = a.ToLowerInvariant + Dim c = a?.ToLowerInvariant + End Sub +End Class +"; + + await new VerifyVB.Test + { + TestState = { Sources = { source } }, + FixedState = { Sources = { fixedSource } }, + CodeActionIndex = 1, + CodeActionEquivalenceKey = nameof(MicrosoftNetCoreAnalyzersResources.UseInvariantVersion), + }.RunAsync(); + } + [Fact] public async Task CA1311_FixToUpperCSharpAsync_SpecifyCurrentCulture() { @@ -268,6 +340,42 @@ End Class }.RunAsync(); } + [Fact] + public async Task CA1311_FixToUpperBasicAsync_SpecifyCurrentCulture_MemberAccessSyntax() + { + var source = @" +Imports System.Globalization +Class C + Sub M() + Dim a = ""test"" + a.[|ToUpper|] + a?.[|ToUpper|] + Dim b = a.[|ToUpper|] + Dim c = a?.[|ToUpper|] + End Sub +End Class +"; + + var fixedSource = @" +Imports System.Globalization +Class C + Sub M() + Dim a = ""test"" + a.ToUpper(CultureInfo.CurrentCulture) + a?.ToUpper(CultureInfo.CurrentCulture) + Dim b = a.ToUpper(CultureInfo.CurrentCulture) + Dim c = a?.ToUpper(CultureInfo.CurrentCulture) + End Sub +End Class +"; + await new VerifyVB.Test + { + TestState = { Sources = { source } }, + FixedState = { Sources = { fixedSource } }, + CodeActionIndex = 0, + CodeActionEquivalenceKey = nameof(MicrosoftNetCoreAnalyzersResources.SpecifyCurrentCulture), + }.RunAsync(); + } [Fact] public async Task CA1311_FixToUpperBasicAsync_UseInvariantVersion() @@ -290,6 +398,42 @@ Sub M() a?.ToUpperInvariant() End Sub End Class +"; + + await new VerifyVB.Test + { + TestState = { Sources = { source } }, + FixedState = { Sources = { fixedSource } }, + CodeActionIndex = 1, + CodeActionEquivalenceKey = nameof(MicrosoftNetCoreAnalyzersResources.UseInvariantVersion), + }.RunAsync(); + } + + [Fact] + public async Task CA1311_FixToUpperBasicAsync_UseInvariantVersion_MemberAccessSyntax() + { + const string source = @" +Class C + Sub M() + Dim a = ""test"" + a.[|ToUpper|] + a?.[|ToUpper|] + Dim b = a.[|ToUpper|] + Dim c = a?.[|ToUpper|] + End Sub +End Class +"; + + const string fixedSource = @" +Class C + Sub M() + Dim a = ""test"" + a.ToUpperInvariant + a?.ToUpperInvariant + Dim b = a.ToUpperInvariant + Dim c = a?.ToUpperInvariant + End Sub +End Class "; await new VerifyVB.Test diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.Fixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.Fixer.vb index 4691492e97..2765eadd63 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.Fixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.Fixer.vb @@ -21,25 +21,41 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Runtime End Function Protected Overrides Async Function SpecifyCurrentCultureAsync(document As Document, generator As SyntaxGenerator, root As SyntaxNode, node As SyntaxNode, cancellationToken As CancellationToken) As Task(Of Document) - If node.IsKind(SyntaxKind.IdentifierName) Then - Dim invocation = node.Parent?.FirstAncestorOrSelf(Of InvocationExpressionSyntax) - If invocation IsNot Nothing Then - Dim model = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False) - Dim symbolInfo = model.GetSymbolInfo(node, cancellationToken).Symbol - Dim methodSymbol = TryCast(symbolInfo, IMethodSymbol) - - If methodSymbol IsNot Nothing And methodSymbol.Parameters.Length = 0 Then - Dim newArg = generator.Argument(CreateCurrentCultureMemberAccess(generator, model)).WithAdditionalAnnotations(Formatter.Annotation) - Dim newInvocation = invocation.AddArgumentListArguments(DirectCast(newArg, ArgumentSyntax)).WithAdditionalAnnotations(Formatter.Annotation) - Dim newRoot = root.ReplaceNode(invocation, newInvocation) - Return document.WithSyntaxRoot(newRoot) - End If + If ShouldFix(node) Then + Dim memberAccess = DirectCast(node.Parent, MemberAccessExpressionSyntax) + + If memberAccess.Parent Is Nothing Or Not memberAccess.Parent.IsKind(SyntaxKind.InvocationExpression) Then + Return Await SpecifyCurrentCultureWhenTheresNoArgumentListAsync(document, generator, root, memberAccess, memberAccess, cancellationToken) + End If + + Dim invocation = DirectCast(memberAccess.Parent, InvocationExpressionSyntax) + If invocation.ArgumentList Is Nothing Then + Return Await SpecifyCurrentCultureWhenTheresNoArgumentListAsync(document, generator, root, memberAccess, invocation, cancellationToken) + End If + + Dim model = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False) + Dim symbolInfo = model.GetSymbolInfo(node, cancellationToken).Symbol + Dim methodSymbol = TryCast(symbolInfo, IMethodSymbol) + + If methodSymbol IsNot Nothing And methodSymbol.Parameters.Length = 0 Then + Dim newArg = generator.Argument(CreateCurrentCultureMemberAccess(generator, model)).WithAdditionalAnnotations(Formatter.Annotation) + Dim newInvocation = invocation.AddArgumentListArguments(DirectCast(newArg, ArgumentSyntax)).WithAdditionalAnnotations(Formatter.Annotation) + Dim newRoot = root.ReplaceNode(invocation, newInvocation) + Return document.WithSyntaxRoot(newRoot) End If End If Return document End Function + Private Async Function SpecifyCurrentCultureWhenTheresNoArgumentListAsync(document As Document, generator As SyntaxGenerator, root As SyntaxNode, memberAccess As MemberAccessExpressionSyntax, nodeToReplace As SyntaxNode, cancellationToken As CancellationToken) As Task(Of Document) + Dim model = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False) + Dim newArg = generator.Argument(CreateCurrentCultureMemberAccess(generator, model)).WithAdditionalAnnotations(Formatter.Annotation) + Dim invocation = generator.InvocationExpression(memberAccess.WithoutTrailingTrivia(), newArg).WithAdditionalAnnotations(Formatter.Annotation) + Dim newRoot = root.ReplaceNode(nodeToReplace, invocation) + Return document.WithSyntaxRoot(newRoot) + End Function + Protected Overrides Function UseInvariantVersionAsync(document As Document, generator As SyntaxGenerator, root As SyntaxNode, node As SyntaxNode) As Task(Of Document) If ShouldFix(node) Then Dim memberAccess = DirectCast(node.Parent, MemberAccessExpressionSyntax) diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.vb b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.vb index e6c86581c4..5f4dc4482a 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicSpecifyCultureForToLowerAndToUpper.vb @@ -11,15 +11,21 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Runtime Public Class BasicSpecifyCultureForToLowerAndToUpperAnalyzer Inherits SpecifyCultureForToLowerAndToUpperAnalyzer - Protected Overrides Function GetMethodNameLocation(invocationNode As SyntaxNode) As Location - Debug.Assert(invocationNode.IsKind(SyntaxKind.InvocationExpression)) + Protected Overrides Function GetMethodNameLocation(node As SyntaxNode) As Location + Debug.Assert(node.IsKind(SyntaxKind.InvocationExpression) OrElse node.IsKind(SyntaxKind.SimpleMemberAccessExpression)) - Dim invocation = CType(invocationNode, InvocationExpressionSyntax) - If invocation.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression) Then - Return DirectCast(invocation.Expression, MemberAccessExpressionSyntax).Name.GetLocation() + If node.IsKind(SyntaxKind.InvocationExpression) Then + Dim invocation = DirectCast(node, InvocationExpressionSyntax) + If invocation.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression) Then + Return DirectCast(invocation.Expression, MemberAccessExpressionSyntax).Name.GetLocation() + End If End If - Return invocation.GetLocation() + If node.IsKind(SyntaxKind.SimpleMemberAccessExpression) Then + Return DirectCast(node, MemberAccessExpressionSyntax).Name.GetLocation() + End If + + Return node.GetLocation() End Function End Class End Namespace