diff --git a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpRecommendCaseInsensitiveStringComparisonFixer.cs b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpRecommendCaseInsensitiveStringComparisonFixer.cs index 5e4e66b03b..f070ca48f1 100644 --- a/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpRecommendCaseInsensitiveStringComparisonFixer.cs +++ b/src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpRecommendCaseInsensitiveStringComparisonFixer.cs @@ -17,70 +17,91 @@ namespace Microsoft.NetCore.CSharp.Analyzers.Performance [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public sealed class CSharpRecommendCaseInsensitiveStringComparisonFixer : RecommendCaseInsensitiveStringComparisonFixer { - protected override IEnumerable GetNewArgumentsForInvocation(SyntaxGenerator generator, string caseChangingApproachValue, IInvocationOperation mainInvocationOperation, - INamedTypeSymbol stringComparisonType, out SyntaxNode? mainInvocationInstance) + protected override IEnumerable GetNewArgumentsForInvocation(SyntaxGenerator generator, + string caseChangingApproachValue, IInvocationOperation mainInvocationOperation, INamedTypeSymbol stringComparisonType, + string? leftOffendingMethod, string? rightOffendingMethod, out SyntaxNode? mainInvocationInstance) { - List arguments = new(); - bool isAnyArgumentNamed = false; - InvocationExpressionSyntax invocationExpression = (InvocationExpressionSyntax)mainInvocationOperation.Syntax; - bool isChangingCaseInArgument = false; mainInvocationInstance = null; if (invocationExpression.Expression is MemberAccessExpressionSyntax memberAccessExpression) { - ExpressionSyntax internalExpression = memberAccessExpression.Expression is ParenthesizedExpressionSyntax parenthesizedExpression ? - parenthesizedExpression.Expression : - memberAccessExpression.Expression; + ExpressionSyntax internalExpression = memberAccessExpression.Expression; + while (internalExpression is ParenthesizedExpressionSyntax parenthesizedExpression) + { + internalExpression = parenthesizedExpression.Expression; + } - if (internalExpression is InvocationExpressionSyntax internalInvocationExpression && - internalInvocationExpression.Expression is MemberAccessExpressionSyntax internalMemberAccessExpression) + if (leftOffendingMethod != null && + internalExpression is InvocationExpressionSyntax internalInvocationExpression && + internalInvocationExpression.Expression is MemberAccessExpressionSyntax internalMemberAccessExpression && + internalMemberAccessExpression.Name.Identifier.Text == leftOffendingMethod) { + // We know we have an instance invocation that is an offending method, retrieve just the instance mainInvocationInstance = internalMemberAccessExpression.Expression; } else { mainInvocationInstance = memberAccessExpression.Expression; - isChangingCaseInArgument = true; } } - foreach (ArgumentSyntax node in invocationExpression.ArgumentList.Arguments) - { - string? argumentName = node.NameColon?.Name.Identifier.ValueText; - isAnyArgumentNamed |= argumentName != null; + List arguments = new(); + bool isAnyArgumentNamed = false; - ExpressionSyntax argumentExpression = node.Expression is ParenthesizedExpressionSyntax argumentParenthesizedExpression ? - argumentParenthesizedExpression.Expression : - node.Expression; + foreach (IArgumentOperation arg in mainInvocationOperation.Arguments) + { + SyntaxNode newArgumentNode; - MemberAccessExpressionSyntax? argumentMemberAccessExpression = null; - if (argumentExpression is InvocationExpressionSyntax argumentInvocationExpression) + // When accessing the main invocation operation arguments, the bottom operation is retrieved + // so we need to go up until we find the actual argument syntax ancestor, and skip through any + // parenthesized syntax nodes + SyntaxNode actualArgumentNode = arg.Syntax; + while (actualArgumentNode is not ArgumentSyntax) { - argumentMemberAccessExpression = argumentInvocationExpression.Expression as MemberAccessExpressionSyntax; + actualArgumentNode = actualArgumentNode.Parent!; } - SyntaxNode newArgumentNode; - if (isChangingCaseInArgument) + string? argumentName = ((ArgumentSyntax)actualArgumentNode).NameColon?.Name.Identifier.ValueText; + isAnyArgumentNamed |= argumentName != null; + + // The arguments could be named and out of order, so we need to detect the string parameter + // and remove the offending invocation if there is one + if (rightOffendingMethod != null && arg.Parameter?.Type?.Name == StringTypeName) { - if (argumentMemberAccessExpression != null) + ExpressionSyntax? desiredExpression = null; + if (arg.Syntax is ArgumentSyntax argumentExpression) + { + desiredExpression = argumentExpression.Expression; + while (desiredExpression is ParenthesizedExpressionSyntax parenthesizedExpression) + { + desiredExpression = parenthesizedExpression.Expression; + } + } + else if (arg.Syntax is InvocationExpressionSyntax argumentInvocationExpression) + { + desiredExpression = argumentInvocationExpression; + } + + if (desiredExpression is InvocationExpressionSyntax invocation && + invocation.Expression is MemberAccessExpressionSyntax argumentMemberAccessExpression) { newArgumentNode = argumentName == RCISCAnalyzer.StringParameterName ? - generator.Argument(RCISCAnalyzer.StringParameterName, RefKind.None, argumentMemberAccessExpression.Expression) : - generator.Argument(argumentMemberAccessExpression.Expression); + generator.Argument(RCISCAnalyzer.StringParameterName, RefKind.None, argumentMemberAccessExpression.Expression) : + generator.Argument(argumentMemberAccessExpression.Expression); } else { - newArgumentNode = node; + newArgumentNode = arg.Syntax; } } else { - newArgumentNode = node; + newArgumentNode = arg.Syntax; } - arguments.Add(newArgumentNode.WithTriviaFrom(node)); + arguments.Add(newArgumentNode.WithTriviaFrom(arg.Syntax)); } Debug.Assert(mainInvocationInstance != null); diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx index 72017396c9..de7327551c 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx @@ -2012,29 +2012,29 @@ Widening and user defined conversions are not supported with generic types. Use the 'string.{0}(string, StringComparison)' overload - - Use 'string.Equals(string, StringComparison)' - - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. - Prefer using 'StringComparer' to perform a case-insensitive comparison + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + + + Use 'string.Equals(string, StringComparison)' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' Use 'TryAdd(TKey, TValue)' diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs index b77cc41997..9b1493d3fe 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs @@ -38,10 +38,8 @@ public sealed class RecommendCaseInsensitiveStringComparisonAnalyzer : Diagnosti internal const string StringEqualsMethodName = "Equals"; internal const string StringParameterName = "value"; internal const string StringComparisonParameterName = "comparisonType"; - internal const string CaseChangingApproachName = "CaseChangingApproach"; - internal const string OffendingMethodName = "OffendingMethodName"; - internal const string LeftOffendingMethodName = "LeftOffendingMethodName"; - internal const string RightOffendingMethodName = "RightOffendingMethodName"; + internal const string LeftOffendingMethodName = "LeftOffendingMethod"; + internal const string RightOffendingMethodName = "RightOffendingMethod"; internal static readonly DiagnosticDescriptor RecommendCaseInsensitiveStringComparisonRule = DiagnosticDescriptorHelper.Create( RuleId, @@ -213,11 +211,11 @@ private void AnalyzeCompilationStart(CompilationStartAnalysisContext context) return; } - // a.ToLower().Method() + // a.ToLower().Method(b.ToLower()) context.RegisterOperationAction(context => { - IInvocationOperation caseChangingInvocation = (IInvocationOperation)context.Operation; - AnalyzeInvocation(context, caseChangingInvocation, stringType, + IInvocationOperation invocation = (IInvocationOperation)context.Operation; + AnalyzeInvocation(context, invocation, stringType, containsStringMethod, startsWithStringMethod, compareToStringMethod, indexOfStringMethod, indexOfStringInt32Method, indexOfStringInt32Int32Method); }, OperationKind.Invocation); @@ -231,41 +229,63 @@ private void AnalyzeCompilationStart(CompilationStartAnalysisContext context) }, OperationKind.Binary); } - private static void AnalyzeInvocation(OperationAnalysisContext context, IInvocationOperation caseChangingInvocation, INamedTypeSymbol stringType, + private static void AnalyzeInvocation(OperationAnalysisContext context, IInvocationOperation invocation, INamedTypeSymbol stringType, IMethodSymbol containsStringMethod, IMethodSymbol startsWithStringMethod, IMethodSymbol compareToStringMethod, IMethodSymbol indexOfStringMethod, IMethodSymbol indexOfStringInt32Method, IMethodSymbol indexOfStringInt32Int32Method) { - if (!IsOffendingMethod(caseChangingInvocation, stringType, out string? offendingMethodName)) + IMethodSymbol diagnosableMethod = invocation.TargetMethod; + + DiagnosticDescriptor? chosenRule; + if (diagnosableMethod.Equals(containsStringMethod) || + diagnosableMethod.Equals(startsWithStringMethod) || + diagnosableMethod.Equals(indexOfStringMethod) || + diagnosableMethod.Equals(indexOfStringInt32Method) || + diagnosableMethod.Equals(indexOfStringInt32Int32Method)) { - return; + chosenRule = RecommendCaseInsensitiveStringComparisonRule; } - - if (!TryGetInvocationWithoutParentheses(caseChangingInvocation, out IInvocationOperation? diagnosableInvocation)) + else if (diagnosableMethod.Equals(compareToStringMethod)) + { + chosenRule = RecommendCaseInsensitiveStringComparerRule; + } + else { return; } - string caseChangingApproach = GetCaseChangingApproach(offendingMethodName); + bool atLeastOneOffendingInvocation = false; - ImmutableDictionary dict = new Dictionary() + // First check if this is a case where the instance is a string that resulted from an offending + // invocation, like {a.ToLower()}.Contains(), in which case we can collect the left side. + string? leftOffendingMethodName = null; + if (TryGetInvocationWithoutParentheses(invocation.Instance, out IInvocationOperation? maybeLeftOffendingInvocation)) { - { CaseChangingApproachName, caseChangingApproach } - }.ToImmutableDictionary(); - - IMethodSymbol diagnosableMethod = diagnosableInvocation.TargetMethod; + atLeastOneOffendingInvocation = IsOffendingMethod(maybeLeftOffendingInvocation, stringType, out leftOffendingMethodName); + } - if (diagnosableMethod.Equals(containsStringMethod) || - diagnosableMethod.Equals(startsWithStringMethod) || - diagnosableMethod.Equals(indexOfStringMethod) || - diagnosableMethod.Equals(indexOfStringInt32Method) || - diagnosableMethod.Equals(indexOfStringInt32Int32Method)) + // Now check if the first argument of Contains|StartsWith|IndexOf is an invocation on a string + // instance of one of the offending methods, in which case, we can collect the right side. + Debug.Assert(!invocation.Arguments.IsEmpty); + string? rightOffendingMethodName = null; + if (TryGetInvocationWithoutParentheses(invocation.Arguments[0].Value, out IInvocationOperation? maybeRightOffendingInvocation)) { - context.ReportDiagnostic(diagnosableInvocation.CreateDiagnostic(RecommendCaseInsensitiveStringComparisonRule, dict, diagnosableMethod.Name)); + atLeastOneOffendingInvocation |= IsOffendingMethod(maybeRightOffendingInvocation, stringType, out rightOffendingMethodName); } - else if (diagnosableMethod.Equals(compareToStringMethod)) + + if (!atLeastOneOffendingInvocation) { - context.ReportDiagnostic(diagnosableInvocation.CreateDiagnostic(RecommendCaseInsensitiveStringComparerRule, dict)); + // For a diagnosis on an invocation operation, either the instance of the invocation + // or the string instance of the first argument need to be an offending method. + return; } + + ImmutableDictionary dict = new Dictionary() + { + { LeftOffendingMethodName, leftOffendingMethodName }, + { RightOffendingMethodName, rightOffendingMethodName } + }.ToImmutableDictionary(); + + context.ReportDiagnostic(invocation.CreateDiagnostic(chosenRule, dict, diagnosableMethod)); } private static void AnalyzeBinaryOperation(OperationAnalysisContext context, IBinaryOperation binaryOperation, INamedTypeSymbol stringType) @@ -286,44 +306,43 @@ private static void AnalyzeBinaryOperation(OperationAnalysisContext context, IBi string? rightOffendingMethodName = null; if (TryGetInvocationWithoutParentheses(binaryOperation.RightOperand, out IInvocationOperation? rightInvocation)) { - atLeastOneOffendingInvocation = IsOffendingMethod(rightInvocation, stringType, out rightOffendingMethodName); + atLeastOneOffendingInvocation |= IsOffendingMethod(rightInvocation, stringType, out rightOffendingMethodName); } - if (atLeastOneOffendingInvocation) + if (!atLeastOneOffendingInvocation) { - string caseChangingApproachValue = GetPreferredCaseChangingApproach(leftOffendingMethodName, rightOffendingMethodName); + // For a diagnosis on a binary operation, at least one of the two sides needs to + // be an invocation of an offending method over a string instance. + return; + } - ImmutableDictionary dict = new Dictionary() + ImmutableDictionary dict = new Dictionary() { - { CaseChangingApproachName, caseChangingApproachValue } + { LeftOffendingMethodName, leftOffendingMethodName }, + { RightOffendingMethodName, rightOffendingMethodName } }.ToImmutableDictionary(); - context.ReportDiagnostic(binaryOperation.CreateDiagnostic(RecommendCaseInsensitiveStringEqualsRule, dict)); - } + context.ReportDiagnostic(binaryOperation.CreateDiagnostic(RecommendCaseInsensitiveStringEqualsRule, dict)); } - private static bool TryGetInvocationWithoutParentheses(IOperation operation, + private static bool TryGetInvocationWithoutParentheses(IOperation? operation, [NotNullWhen(returnValue: true)] out IInvocationOperation? diagnosableInvocation) { diagnosableInvocation = null; - if (operation is not IInvocationOperation invocationOperation) + + IOperation? descendant = operation; + while (descendant is IParenthesizedOperation parenthesizedOperation) { - return false; + descendant = parenthesizedOperation.Operand; } - IOperation? ancestor = invocationOperation.WalkUpParentheses().WalkUpConversion().Parent; - - if (ancestor is IInvocationOperation invocationAncestor) + if (descendant is IInvocationOperation invocationDescendant) { - diagnosableInvocation = invocationAncestor; + diagnosableInvocation = invocationDescendant; } - else if (ancestor is IArgumentOperation argumentAncestor && argumentAncestor.Parent is IInvocationOperation argumentInvocationAncestor) + else if (descendant is IArgumentOperation argumentDescendant && argumentDescendant.Value is IInvocationOperation argumentInvocationDescendant) { - diagnosableInvocation = argumentInvocationAncestor; - } - else - { - diagnosableInvocation = invocationOperation; + diagnosableInvocation = argumentInvocationDescendant; } return diagnosableInvocation != null; @@ -355,29 +374,5 @@ private static bool IsOffendingMethod(IInvocationOperation invocation, ITypeSymb offendingMethodName = invocation.TargetMethod.Name; return true; } - - private static string GetCaseChangingApproach(string methodName) - { - if (methodName is StringToLowerMethodName or StringToUpperMethodName) - { - return StringComparisonCurrentCultureIgnoreCaseName; - } - - Debug.Assert(methodName is StringToLowerInvariantMethodName or StringToUpperInvariantMethodName); - return StringComparisonInvariantCultureIgnoreCaseName; - } - - private static string GetPreferredCaseChangingApproach(string? leftOffendingMethodName, string? rightOffendingMethodName) - { - if (leftOffendingMethodName is StringToLowerMethodName or StringToUpperMethodName || - rightOffendingMethodName is StringToLowerMethodName or StringToUpperMethodName) - { - return StringComparisonCurrentCultureIgnoreCaseName; - } - - Debug.Assert(leftOffendingMethodName is StringToLowerInvariantMethodName or StringToUpperInvariantMethodName || - rightOffendingMethodName is StringToLowerInvariantMethodName or StringToUpperInvariantMethodName); - return StringComparisonInvariantCultureIgnoreCaseName; - } } } diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Fixer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Fixer.cs index d4ce31c0b2..3cf6cdf3d5 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Fixer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Fixer.cs @@ -22,8 +22,11 @@ namespace Microsoft.NetCore.Analyzers.Performance /// public abstract class RecommendCaseInsensitiveStringComparisonFixer : CodeFixProvider { - protected abstract IEnumerable GetNewArgumentsForInvocation(SyntaxGenerator generator, string caseChangingApproachValue, IInvocationOperation mainInvocationOperation, - INamedTypeSymbol stringComparisonType, out SyntaxNode? mainInvocationInstance); + protected const string StringTypeName = "String"; + + protected abstract IEnumerable GetNewArgumentsForInvocation(SyntaxGenerator generator, + string caseChangingApproachValue, IInvocationOperation mainInvocationOperation, INamedTypeSymbol stringComparisonType, + string? leftOffendingMethod, string? rightOffendingMethod, out SyntaxNode? mainInvocationInstance); protected abstract IEnumerable GetNewArgumentsForBinary(SyntaxGenerator generator, SyntaxNode rightNode, SyntaxNode typeMemberAccess); @@ -60,16 +63,53 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxGenerator generator = SyntaxGenerator.GetGenerator(doc); - // The desired case changing enum value should've already been chosen in the analyzer - if (!context.Diagnostics[0].Properties.TryGetValue(RCISCAnalyzer.CaseChangingApproachName, out string? caseChangingApproachValue) || caseChangingApproachValue == null) + ImmutableDictionary dict = context.Diagnostics[0].Properties; + + // The dictionary should contain the keys for both left and right offending methods, + // and at least one of them should not be null. + if (!dict.TryGetValue(RCISCAnalyzer.LeftOffendingMethodName, out string? leftOffendingMethod) || + !dict.TryGetValue(RCISCAnalyzer.RightOffendingMethodName, out string? rightOffendingMethod) || + (leftOffendingMethod == null && rightOffendingMethod == null)) + { + return; + } + + bool leftIsToLowerOrToUpper = leftOffendingMethod is RCISCAnalyzer.StringToLowerMethodName or RCISCAnalyzer.StringToUpperMethodName; + bool rightIsToLowerOrToUpper = rightOffendingMethod is RCISCAnalyzer.StringToLowerMethodName or RCISCAnalyzer.StringToUpperMethodName; + + bool leftIsToLowerInvariantOrToUpperInvariant = leftOffendingMethod is RCISCAnalyzer.StringToLowerInvariantMethodName or RCISCAnalyzer.StringToUpperInvariantMethodName; + bool rightIsToLowerInvariantOrToUpperInvariant = rightOffendingMethod is RCISCAnalyzer.StringToLowerInvariantMethodName or RCISCAnalyzer.StringToUpperInvariantMethodName; + + // If the cultures of the two strings are incompatible, do not offer a fix + if ((leftIsToLowerOrToUpper && rightIsToLowerInvariantOrToUpperInvariant) || + (rightIsToLowerOrToUpper && leftIsToLowerInvariantOrToUpperInvariant)) { return; } + string? caseChangingApproachValue = null; + if (leftIsToLowerOrToUpper || rightIsToLowerOrToUpper) + { + caseChangingApproachValue = RCISCAnalyzer.StringComparisonCurrentCultureIgnoreCaseName; + } + else if (leftIsToLowerInvariantOrToUpperInvariant || rightIsToLowerInvariantOrToUpperInvariant) + { + caseChangingApproachValue = RCISCAnalyzer.StringComparisonInvariantCultureIgnoreCaseName; + } + + Debug.Assert(caseChangingApproachValue != null, "Unexpected offending methods"); + if (operation is IInvocationOperation invocation) { + if (invocation.TargetMethod.Name is RCISCAnalyzer.StringCompareToMethodName) + { + // Never offer a fix for CompareTo + return; + } + Task createChangedDocument(CancellationToken _) => FixInvocationAsync(generator, doc, root, - invocation, stringComparisonType, invocation.TargetMethod.Name, caseChangingApproachValue); + invocation, stringComparisonType, invocation.TargetMethod.Name, + caseChangingApproachValue!, leftOffendingMethod, rightOffendingMethod); string title = string.Format(System.Globalization.CultureInfo.CurrentCulture, MicrosoftNetCoreAnalyzersResources.RecommendCaseInsensitiveStringComparerStringComparisonCodeFixTitle, invocation.TargetMethod.Name); @@ -84,7 +124,7 @@ Task createChangedDocument(CancellationToken _) => FixInvocationAsync( else if (operation is IBinaryOperation binaryOperation && binaryOperation.LeftOperand != null && binaryOperation.RightOperand != null) { - Task createChangedDocument(CancellationToken _) => FixBinaryAsync(generator, doc, root, binaryOperation, stringComparisonType, caseChangingApproachValue); + Task createChangedDocument(CancellationToken _) => FixBinaryAsync(generator, doc, root, binaryOperation, stringComparisonType, caseChangingApproachValue!); string title = MicrosoftNetCoreAnalyzersResources.RecommendCaseInsensitiveStringEqualsCodeFixTitle; @@ -98,7 +138,8 @@ Task createChangedDocument(CancellationToken _) => FixInvocationAsync( } private Task FixInvocationAsync(SyntaxGenerator generator, Document doc, SyntaxNode root, IInvocationOperation mainInvocation, - INamedTypeSymbol stringComparisonType, string diagnosableMethodName, string caseChangingApproachValue) + INamedTypeSymbol stringComparisonType, string diagnosableMethodName, + string caseChangingApproachValue, string? leftOffendingMethod, string? rightOffendingMethod) { // Defensive check: The max number of arguments is held by IndexOf Debug.Assert(mainInvocation.Arguments.Length <= 3); @@ -122,13 +163,15 @@ private Task FixInvocationAsync(SyntaxGenerator generator, Document do // B) a.IndexOf(b, startIndex: n, StringComparison.Desired) // C) a.IndexOf(b, startIndex: n, count: m, StringComparison.Desired) - // Defensive check: Should not fix string.CompareTo + // Defensive check: Should not fix string.CompareTo (or any other method) Debug.Assert(diagnosableMethodName is RCISCAnalyzer.StringContainsMethodName or RCISCAnalyzer.StringIndexOfMethodName or RCISCAnalyzer.StringStartsWithMethodName); - IEnumerable newArguments = GetNewArgumentsForInvocation(generator, caseChangingApproachValue, mainInvocation, stringComparisonType, out SyntaxNode? mainInvocationInstance); + IEnumerable newArguments = GetNewArgumentsForInvocation(generator, + caseChangingApproachValue, mainInvocation, stringComparisonType, + leftOffendingMethod, rightOffendingMethod, out SyntaxNode? mainInvocationInstance); SyntaxNode stringMemberAccessExpression = generator.MemberAccessExpression(mainInvocationInstance, mainInvocation.TargetMethod.Name); 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 43d310dde9..e777c0c778 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf @@ -2244,48 +2244,48 @@ Obecné přetypování (IL unbox.any) používané sekvencí vrácenou metodou E - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Při použití CompareTo se vyhněte volání ToLower, ToUpper, ToLowerInvariant a ToUpperInvariant pro porovnávání řetězců bez rozlišení velikosti písmen, protože vedou k alokaci. Místo toho použijte StringComparer pro porovnávání bez ohledu na velikost písmen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Při použití CompareTo se vyhněte volání ToLower, ToUpper, ToLowerInvariant a ToUpperInvariant pro porovnávání řetězců bez rozlišení velikosti písmen, protože vedou k alokaci. Místo toho použijte StringComparer pro porovnávání bez ohledu na velikost písmen. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Preferovat použití StringComparer pro porovnávání bez rozlišování velkých a malých písmen + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Preferovat použití StringComparer pro porovnávání bez rozlišování velkých a malých písmen Use the 'string.{0}(string, StringComparison)' overload - Použijte přetížení string.{0}(string, StringComparison) + Použijte přetížení string.{0}(string, StringComparison) - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Vyhněte se volání ToLower, ToUpper, ToLowerInvariant a ToUpperInvariant pro porovnávání řetězců bez ohledu na velikost písmen, protože vedou k alokaci. Místo toho raději volejte přetížení metod Contains, IndexOf a StartsWith, které přebírají hodnotu výčtu StringComparison, aby se provedlo porovnání bez ohledu na velikost písmen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Preferovat přetížení metody porovnání řetězců {0}, která přebírá hodnotu výčtu StringComparison a provádí porovnání bez rozlišení velkých a malých písmen. + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Preferovat přetížení metody StringComparison pro porovnávání řetězců bez ohledu na velikost písmen. + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Preferovat přetížení metody StringComparison pro porovnávání řetězců bez ohledu na velikost písmen. Use 'string.Equals(string, StringComparison)' - Použijte string.Equals(string, StringComparison) + Použijte string.Equals(string, StringComparison) - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Vyhněte se volání ToLower, ToUpper, ToLowerInvariant a ToUpperInvariant k provádění porovnávání řetězců bez rozlišování velkých a malých písmen, jako v string.ToLower() == string.ToLower(), protože vedou k přidělení. Místo toho použijte string.Equals(string, StringComparison) pro porovnání bez rozlišování malých a velkých písmen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Vyhněte se volání ToLower, ToUpper, ToLowerInvariant a ToUpperInvariant k provádění porovnávání řetězců bez rozlišování velkých a malých písmen, jako v string.ToLower() == string.ToLower(), protože vedou k přidělení. Místo toho použijte string.Equals(string, StringComparison) pro porovnání bez rozlišování malých a velkých písmen. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Preferujte použití string.Equals(string, StringComparison) pro porovnání bez rozlišování velkých a malých písmen + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Preferujte použití string.Equals(string, StringComparison) pro porovnání bez rozlišování velkých a malých písmen 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 ff3b8f8b1c..c7e9897ab1 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf @@ -2244,48 +2244,48 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Vermeiden Sie das Aufrufen von "ToLower", "ToUpper", "ToLowerInvariant" und "ToUpperInvariant", um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung bei Verwendung von "CompareTo" durchzuführen, da sie zu einer Zuordnung führen. Verwenden Sie stattdessen "StringComparer", um Vergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Vermeiden Sie das Aufrufen von "ToLower", "ToUpper", "ToLowerInvariant" und "ToUpperInvariant", um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung bei Verwendung von "CompareTo" durchzuführen, da sie zu einer Zuordnung führen. Verwenden Sie stattdessen "StringComparer", um Vergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Verwenden Sie "StringComparer" vor, um einen Vergleich ohne Beachtung der Groß-/Kleinschreibung durchzuführen. + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Verwenden Sie "StringComparer" vor, um einen Vergleich ohne Beachtung der Groß-/Kleinschreibung durchzuführen. Use the 'string.{0}(string, StringComparison)' overload - Verwenden Sie die "string.{0}(string, StringComparison)"-Überladung + Verwenden Sie die "string.{0}(string, StringComparison)"-Überladung - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Vermeiden Sie das Aufrufen von "ToLower", "ToUpper", "ToLowerInvariant" und "ToUpperInvariant", um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen, da sie zu einer Zuordnung führen. Rufen Sie stattdessen lieber die Methodenüberladungen von "Contains", "IndexOf" und "StartsWith" auf, die einen StringComparison-Enumerationswert verwenden, um Vergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Bevorzugen Sie die Methodenüberladung des Zeichenfolgenvergleichs von "{0}", die einen Enumerationswert "StringComparison" verwendet, um einen Vergleich ohne Beachtung der Groß-/Kleinschreibung durchzuführen. + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - "StringComparison"-Methodenüberladungen bevorzugen, um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + "StringComparison"-Methodenüberladungen bevorzugen, um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen Use 'string.Equals(string, StringComparison)' - Verwenden Sie "string.Equals(string, StringComparison)" + Verwenden Sie "string.Equals(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Vermeiden Sie den Aufruf von "ToLower", "ToUpper", "ToLowerInvariant" und "ToUpperInvariant", um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen, wie in "string.ToLower() == Zeichenfolge. ToLower()", da sie zu einer Zuordnung führen. Verwenden Sie stattdessen "string.Equals(string, StringComparison)", um Vergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Vermeiden Sie den Aufruf von "ToLower", "ToUpper", "ToLowerInvariant" und "ToUpperInvariant", um Zeichenfolgenvergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen, wie in "string.ToLower() == Zeichenfolge. ToLower()", da sie zu einer Zuordnung führen. Verwenden Sie stattdessen "string.Equals(string, StringComparison)", um Vergleiche ohne Beachtung der Groß-/Kleinschreibung durchzuführen. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Verwenden Sie lieber "string.Equals(string, StringComparison)", um einen Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung durchzuführen + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Verwenden Sie lieber "string.Equals(string, StringComparison)", um einen Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung durchzuführen 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 913fb8f2e8..7f0bf288a8 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf @@ -2244,48 +2244,48 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Evite llamar a "ToLower", "ToUpper", "ToLowerInvariant" y "ToUpperInvariant" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas al usar "CompareTo", porque dan lugar a una asignación. En su lugar, use "StringComparer" para realizar comparaciones sin distinción de mayúsculas y minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Evite llamar a "ToLower", "ToUpper", "ToLowerInvariant" y "ToUpperInvariant" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas al usar "CompareTo", porque dan lugar a una asignación. En su lugar, use "StringComparer" para realizar comparaciones sin distinción de mayúsculas y minúsculas. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Preferir el uso de "StringComparer" para realizar una comparación sin distinción de mayúsculas y minúsculas + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Preferir el uso de "StringComparer" para realizar una comparación sin distinción de mayúsculas y minúsculas Use the 'string.{0}(string, StringComparison)' overload - Usar la sobrecarga "string.{0}(string, StringComparison)" + Usar la sobrecarga "string.{0}(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Evite llamar a "ToLower", "ToUpper", "ToLowerInvariant" y "ToUpperInvariant" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas porque dan lugar a una asignación. En su lugar, es preferible llamar a las sobrecargas de método de "Contains", "IndexOf" y "StartsWith" que toman un valor de enumeración "StringComparison" para realizar comparaciones sin distinción de mayúsculas y minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Preferir la sobrecarga de método de comparación de cadenas de "{0}" que toma un valor de enumeración "StringComparison" para realizar una comparación sin distinción de mayúsculas y minúsculas + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Preferir las sobrecargas del método "StringComparison" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Preferir las sobrecargas del método "StringComparison" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas Use 'string.Equals(string, StringComparison)' - Use "string.Equals(string, StringComparison)" + Use "string.Equals(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Evite llamar a "ToLower", "ToUpper", "ToLowerInvariant" y "ToUpperInvariant" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas como en "string.ToLower() == string.ToLower()", porque dan lugar a una asignación. En su lugar, use "string.Equals(string, StringComparison)" para realizar comparaciones sin distinción de mayúsculas y minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Evite llamar a "ToLower", "ToUpper", "ToLowerInvariant" y "ToUpperInvariant" para realizar comparaciones de cadenas sin distinción de mayúsculas y minúsculas como en "string.ToLower() == string.ToLower()", porque dan lugar a una asignación. En su lugar, use "string.Equals(string, StringComparison)" para realizar comparaciones sin distinción de mayúsculas y minúsculas. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Elija usar "string". Equals(string, StringComparison)" para realizar una comparación sin distinción de mayúsculas y minúsculas + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Elija usar "string". Equals(string, StringComparison)" para realizar una comparación sin distinción de mayúsculas y minúsculas 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 51cbcedeef..b0c69e02a4 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf @@ -2244,48 +2244,48 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Évitez d’appeler 'ToLower', 'ToUpper', 'ToLowerInvariant' et 'ToUpperInvariant' pour effectuer des comparaisons de chaînes qui ne respectent pas la casse lors de l’utilisation de 'CompareTo', car elles entraînent une allocation. Utilisez plutôt 'StringComparer' pour effectuer des comparaisons qui ne respectent pas la casse. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Évitez d’appeler 'ToLower', 'ToUpper', 'ToLowerInvariant' et 'ToUpperInvariant' pour effectuer des comparaisons de chaînes qui ne respectent pas la casse lors de l’utilisation de 'CompareTo', car elles entraînent une allocation. Utilisez plutôt 'StringComparer' pour effectuer des comparaisons qui ne respectent pas la casse. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Préférez utiliser 'StringComparer' pour effectuer une comparaison qui ne respecte pas la casse + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Préférez utiliser 'StringComparer' pour effectuer une comparaison qui ne respecte pas la casse Use the 'string.{0}(string, StringComparison)' overload - Utiliser la surcharge « string.{0}(string, StringComparison) » + Utiliser la surcharge « string.{0}(string, StringComparison) » - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Évitez d’appeler 'ToLower', 'ToUpper', 'ToLowerInvariant' et 'ToUpperInvariant' pour effectuer des comparaisons de chaînes qui ne respectent pas la casse, car elles entraînent une allocation. Préférez plutôt appeler les surcharges de méthode de 'Contains', 'IndexOf' et 'StartsWith' qui acceptent une valeur enum 'StringComparison' pour effectuer des comparaisons qui ne respectent pas la casse. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Préférer la surcharge de méthode de comparaison de chaînes de '{0}' qui accepte une valeur enum 'StringComparison' pour effectuer une comparaison qui ne respecte pas la casse + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Préférer les surcharges de méthode 'StringComparison' pour effectuer des comparaisons de chaînes qui ne respectent pas la casse + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Préférer les surcharges de méthode 'StringComparison' pour effectuer des comparaisons de chaînes qui ne respectent pas la casse Use 'string.Equals(string, StringComparison)' - Utilisez 'string. Equals(string, StringComparison)' + Utilisez 'string. Equals(string, StringComparison)' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Évitez d’appeler « ToLower », « ToUpper », « ToLowerInvariant » et « ToUpperInvariant » pour effectuer des comparaisons de chaînes non sensibles à la casse, comme dans « string ». ToLower() == chaîne. ToLower()', car ils entraînent une allocation. Utilisez plutôt 'string'. Equals(string, StringComparison) » pour effectuer des comparaisons qui ne respectent pas la casse. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Évitez d’appeler « ToLower », « ToUpper », « ToLowerInvariant » et « ToUpperInvariant » pour effectuer des comparaisons de chaînes non sensibles à la casse, comme dans « string ». ToLower() == chaîne. ToLower()', car ils entraînent une allocation. Utilisez plutôt 'string'. Equals(string, StringComparison) » pour effectuer des comparaisons qui ne respectent pas la casse. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Préférer l’utilisation de 'string. Equals(string, StringComparison)' pour effectuer une comparaison qui ne respecte pas la casse + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Préférer l’utilisation de 'string. Equals(string, StringComparison)' pour effectuer une comparaison qui ne respecte pas la casse 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 e18e3a4716..94c84f4cb6 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf @@ -2244,48 +2244,48 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Evitare di chiamare i metodi “ToLower”, “ToUpper”, “ToLowerInvariant” e “ToUpperInvariant” per eseguire confronti di stringhe senza distinzione tra maiuscole e minuscole quando si usa “CompareTo”, perché portano a un'allocazione. Utilizzare invece “StringComparer” per eseguire confronti senza distinzione tra maiuscole e minuscole. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Evitare di chiamare i metodi “ToLower”, “ToUpper”, “ToLowerInvariant” e “ToUpperInvariant” per eseguire confronti di stringhe senza distinzione tra maiuscole e minuscole quando si usa “CompareTo”, perché portano a un'allocazione. Utilizzare invece “StringComparer” per eseguire confronti senza distinzione tra maiuscole e minuscole. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Preferire l'uso di “StringComparer” per eseguire un confronto senza distinzione tra maiuscole e minuscole. + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Preferire l'uso di “StringComparer” per eseguire un confronto senza distinzione tra maiuscole e minuscole. Use the 'string.{0}(string, StringComparison)' overload - Usare l'overload “string.{0}(string, StringComparison)" + Usare l'overload “string.{0}(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Evitare di chiamare “ToLower”, “ToUpper”, “ToLowerInvariant” e “ToUpperInvariant” per eseguire confronti di stringhe senza distinzione tra maiuscole e minuscole, perché comportano un'allocazione. Preferire invece chiamare i sovraccarichi dei metodi “Contains”, “IndexOf” e “StartsWith” che accettano un valore dell'enumerazione “StringComparison” per eseguire confronti senza distinzione tra maiuscole e minuscole. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Preferire il sovraccarico del metodo di confronto tra stringhe '{0}' , che accetta un valore dell'enumerazione “StringComparison” per eseguire un confronto senza distinzione tra maiuscole e minuscole. + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Preferire gli overload di metodo “StringComparison” per eseguire confronti tra stringhe senza distinzione tra maiuscole e minuscole + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Preferire gli overload di metodo “StringComparison” per eseguire confronti tra stringhe senza distinzione tra maiuscole e minuscole Use 'string.Equals(string, StringComparison)' - Usare 'string. Equals(string, StringComparison)' + Usare 'string. Equals(string, StringComparison)' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Evitare di chiamare i metodi “ToLower”, “ToUpper”, “ToLowerInvariant” e “ToUpperInvariant” per eseguire confronti di stringhe senza distinzione tra maiuscole e minuscole come in 'string' ToLower() == stringa. ToLower()', perché comportano un'allocazione. Utilizzare invece 'string. Equals(string, StringComparison)' per eseguire confronti senza distinzione tra maiuscole e minuscole. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Evitare di chiamare i metodi “ToLower”, “ToUpper”, “ToLowerInvariant” e “ToUpperInvariant” per eseguire confronti di stringhe senza distinzione tra maiuscole e minuscole come in 'string' ToLower() == stringa. ToLower()', perché comportano un'allocazione. Utilizzare invece 'string. Equals(string, StringComparison)' per eseguire confronti senza distinzione tra maiuscole e minuscole. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Usare preferibilmente 'string. Equals(string, StringComparison)' per eseguire un confronto senza distinzione tra maiuscole e minuscole + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Usare preferibilmente 'string. Equals(string, StringComparison)' per eseguire un confronto senza distinzione tra maiuscole e minuscole 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 6e5a108de4..b8e983a67b 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf @@ -2244,48 +2244,48 @@ Enumerable.OfType<T> で使用されるジェネリック型チェック ( - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - 'CompareTo' を使用するときに大文字と小文字を区別しない文字列比較を実行するために、'ToLower'、'ToUpper'、'ToLowerInvariant'、および 'ToUpperInvariant' を呼び出さないようにしてください。これは、割り当てにつながるためです。代わりに、'StringComparer' を使用して、大文字と小文字を区別しない比較を実行してください。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + 'CompareTo' を使用するときに大文字と小文字を区別しない文字列比較を実行するために、'ToLower'、'ToUpper'、'ToLowerInvariant'、および 'ToUpperInvariant' を呼び出さないようにしてください。これは、割り当てにつながるためです。代わりに、'StringComparer' を使用して、大文字と小文字を区別しない比較を実行してください。 - Prefer using 'StringComparer' to perform a case-insensitive comparison - 大文字と小文字を区別しない比較を実行するには、'StringComparer' を使用することをお勧めします + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + 大文字と小文字を区別しない比較を実行するには、'StringComparer' を使用することをお勧めします Use the 'string.{0}(string, StringComparison)' overload - 'string.{0}(string, StringComparison)' オーバーロードを使用してください + 'string.{0}(string, StringComparison)' オーバーロードを使用してください - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - 大文字と小文字を区別しない文字列比較を実行するために、'ToLower'、'ToUpper'、'ToLowerInvariant'、および 'ToUpperInvariant' を呼び出さないようにしてください。これは、割り当てにつながるためです。代わりに、'StringComparison' 列挙型の値を取る 'Contains'、'IndexOf'、'StartsWith' のメソッド オーバーロードを呼び出して、大文字と小文字を区別しない比較を実行することをお勧めします。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - 大文字と小文字を区別しない比較を実行するために、'StringComparison' 列挙値を取る '{0}' の文字列比較メソッドオーバーロードをお勧めします + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - 大文字と小文字を区別しない文字列比較を実行するには、'StringComparison' メソッド オーバーロードをお勧めします + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + 大文字と小文字を区別しない文字列比較を実行するには、'StringComparison' メソッド オーバーロードをお勧めします Use 'string.Equals(string, StringComparison)' - 'string.Equals(string, StringComparison)' を使用する + 'string.Equals(string, StringComparison)' を使用する - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - 'string.ToLower() == string.ToLower()' で大文字と小文字を区別しない文字列比較を実行するために、'ToLower'、'ToUpper'、'ToLowerInvariant'、および 'ToUpperInvariant' を呼び出さないようにしてください。これは、割り当てにつながるためです。代わりに、string.Equals(string, StringComparison)' を使用して、大文字と小文字を区別しない比較を実行してください。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + 'string.ToLower() == string.ToLower()' で大文字と小文字を区別しない文字列比較を実行するために、'ToLower'、'ToUpper'、'ToLowerInvariant'、および 'ToUpperInvariant' を呼び出さないようにしてください。これは、割り当てにつながるためです。代わりに、string.Equals(string, StringComparison)' を使用して、大文字と小文字を区別しない比較を実行してください。 - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - 大文字と小文字を区別しない比較を実行するには、'string.Equals(string, StringComparison)' の使用を優先します。 + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + 大文字と小文字を区別しない比較を実行するには、'string.Equals(string, StringComparison)' の使用を優先します。 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 2cb8927d8b..ef2a53d9dc 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf @@ -2244,48 +2244,48 @@ Enumerable.OfType<T>에서 사용하는 제네릭 형식 검사(C# 'is' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - 'CompareTo'를 사용할 때 대/소문자를 구분하지 않는 문자열 비교를 수행하기 위해 'ToLower', 'ToUpper', 'ToLowerInvariant' 및 'ToUpperInvariant'를 호출하지 마세요. 할당으로 이어지기 때문입니다. 대신 'StringComparer'를 사용하여 대소문자를 구분하지 않는 비교를 수행하세요. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + 'CompareTo'를 사용할 때 대/소문자를 구분하지 않는 문자열 비교를 수행하기 위해 'ToLower', 'ToUpper', 'ToLowerInvariant' 및 'ToUpperInvariant'를 호출하지 마세요. 할당으로 이어지기 때문입니다. 대신 'StringComparer'를 사용하여 대소문자를 구분하지 않는 비교를 수행하세요. - Prefer using 'StringComparer' to perform a case-insensitive comparison - 대소문자를 구분하지 않는 비교를 수행하려면 'StringComparer' 사용을 선호합니다. + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + 대소문자를 구분하지 않는 비교를 수행하려면 'StringComparer' 사용을 선호합니다. Use the 'string.{0}(string, StringComparison)' overload - 'string.{0}(string, StringComparison)' 오버로드 사용 + 'string.{0}(string, StringComparison)' 오버로드 사용 - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - 대/소문자를 구분하지 않는 문자열 비교를 수행하기 위해 'ToLower', 'ToUpper', 'ToLowerInvariant' 및 'ToUpperInvariant'를 호출하지 마세요. 대신 대/소문자를 구분하지 않는 비교를 수행하기 위해 'StringComparison' 열거형 값을 사용하는 'Contains', 'IndexOf' 및 'StartsWith'의 메서드 오버로드를 호출하는 것이 좋습니다. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - 대/소문자를 구분하지 않는 비교를 수행하기 위해 'StringComparison' 열거형 값을 사용하는 '{0}'의 문자열 비교 메서드 오버로드를 선호합니다. + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - 대소문자를 구분하지 않는 문자열 비교를 수행하려면 'StringComparison' 메서드 오버로드를 선호합니다. + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + 대소문자를 구분하지 않는 문자열 비교를 수행하려면 'StringComparison' 메서드 오버로드를 선호합니다. Use 'string.Equals(string, StringComparison)' - 'string.Equals(문자열, StringComparison)' 사용 + 'string.Equals(문자열, StringComparison)' 사용 - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - 'ToLower', 'ToUpper', 'ToLowerInvariant' 및 'ToUpperInvariant'를 호출하여 'string.ToLower() == string.ToLower()'에서와 같이 대/소문자를 구분하지 않는 문자열 비교를 수행하지 마세요. 할당으로 이어지기 때문입니다. 대신 대소문자를 구분하지 않는 비교를 수행하려면 'string.Equals(string, StringComparison)'을 사용하세요. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + 'ToLower', 'ToUpper', 'ToLowerInvariant' 및 'ToUpperInvariant'를 호출하여 'string.ToLower() == string.ToLower()'에서와 같이 대/소문자를 구분하지 않는 문자열 비교를 수행하지 마세요. 할당으로 이어지기 때문입니다. 대신 대소문자를 구분하지 않는 비교를 수행하려면 'string.Equals(string, StringComparison)'을 사용하세요. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - 대소문자를 구분하지 않는 비교를 수행하려면 'string.Equals(string, StringComparison)' 사용을 선호하세요. + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + 대소문자를 구분하지 않는 비교를 수행하려면 'string.Equals(string, StringComparison)' 사용을 선호하세요. 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 b5a80ebbf3..5cddc87194 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf @@ -2244,48 +2244,48 @@ Konwersje poszerzane i zdefiniowane przez użytkownika nie są obsługiwane w pr - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Unikaj wywoływania elementów „ToLower”, „ToUpper”, "ToLowerInvariant" i "ToUpperInvariant", aby wykonywać porównania ciągów bez uwzględniania wielkości liter podczas używania elementu „CompareTo”, ponieważ prowadzą one do alokacji. Zamiast tego użyj elementu „StringComparer”, aby wykonać porównania bez uwzględniania wielkości liter. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Unikaj wywoływania elementów „ToLower”, „ToUpper”, "ToLowerInvariant" i "ToUpperInvariant", aby wykonywać porównania ciągów bez uwzględniania wielkości liter podczas używania elementu „CompareTo”, ponieważ prowadzą one do alokacji. Zamiast tego użyj elementu „StringComparer”, aby wykonać porównania bez uwzględniania wielkości liter. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Preferuj używanie elementu „StringComparer” do porównywania bez uwzględniania wielkości liter + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Preferuj używanie elementu „StringComparer” do porównywania bez uwzględniania wielkości liter Use the 'string.{0}(string, StringComparison)' overload - Użyj obciążenia „string.{0}(string, StringComparison)” + Użyj obciążenia „string.{0}(string, StringComparison)” - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Unikaj wywoływania elementów „ToLower”, „ToUpper”, „ToLowerInvariant” i „ToUpperInvariant”, aby przeprowadzać porównania ciągów bez uwzględniania wielkości liter, ponieważ prowadzą do alokacji. Zamiast tego preferuj wywoływanie przeciążeń metod „Contains”, „IndexOf” i „StartsWith”, które przyjmują wartość wyliczenia „StringComparison”, aby wykonać porównania bez uwzględniania wielkości liter. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Preferuj przeciążenie metody porównywania ciągów „{0}”, które przyjmuje wartość wyliczenia „StringComparison” w celu wykonania porównania bez uwzględniania wielkości liter + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Preferuj przeciążenia metody „StringComparison”, aby wykonywać porównania ciągów bez uwzględniania wielkości liter + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Preferuj przeciążenia metody „StringComparison”, aby wykonywać porównania ciągów bez uwzględniania wielkości liter Use 'string.Equals(string, StringComparison)' - Użyj ciągu „string.Equals(string, StringComparison)” + Użyj ciągu „string.Equals(string, StringComparison)” - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Unikaj wywoływania elementów „ToLower”, „ToUpper”, „ToLowerInvariant” i „ToUpperInvariant”, aby wykonywać porównania ciągów bez uwzględniania wielkości liter, jak w przypadku „'string.ToLower() == string.ToLower()”, ponieważ prowadzą one do alokacji. Zamiast tego użyj ciągu „string.Equals(string, StringComparison)”, aby wykonywać porównania bez uwzględniania wielkości liter. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Unikaj wywoływania elementów „ToLower”, „ToUpper”, „ToLowerInvariant” i „ToUpperInvariant”, aby wykonywać porównania ciągów bez uwzględniania wielkości liter, jak w przypadku „'string.ToLower() == string.ToLower()”, ponieważ prowadzą one do alokacji. Zamiast tego użyj ciągu „string.Equals(string, StringComparison)”, aby wykonywać porównania bez uwzględniania wielkości liter. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Preferuj używanie ciągu „string.Equals(string, StringComparison)”, aby wykonać porównanie bez uwzględniania wielkości liter + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Preferuj używanie ciągu „string.Equals(string, StringComparison)”, aby wykonać porównanie bez uwzględniania wielkości liter 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 18278dd817..6f1339e2b3 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 @@ -2244,48 +2244,48 @@ Ampliação e conversões definidas pelo usuário não são compatíveis com tip - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Evite chamar 'ToLower', 'ToUpper', 'ToLowerInvariant' e 'ToUpperInvariant' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas ao usar 'CompareTo', porque elas levam a uma alocação. Em vez disso, use 'StringComparer' para realizar comparações que não diferenciam maiúsculas de minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Evite chamar 'ToLower', 'ToUpper', 'ToLowerInvariant' e 'ToUpperInvariant' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas ao usar 'CompareTo', porque elas levam a uma alocação. Em vez disso, use 'StringComparer' para realizar comparações que não diferenciam maiúsculas de minúsculas. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Prefira usar 'StringComparer' para realizar uma comparação que não diferencia maiúsculas de minúsculas + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Prefira usar 'StringComparer' para realizar uma comparação que não diferencia maiúsculas de minúsculas Use the 'string.{0}(string, StringComparison)' overload - Use a 'cadeia de caracteres.{0}(cadeia de caracteres, StringComparison)' sobrecarga + Use a 'cadeia de caracteres.{0}(cadeia de caracteres, StringComparison)' sobrecarga - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Evite chamar 'ToLower', 'ToUpper', 'ToLowerInvariant' e 'ToUpperInvariant' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas porque elas levam a uma alocação. Em vez disso, prefira chamar as sobrecargas de método de 'Contains', 'IndexOf' e 'StartsWith' que usam um valor de enumeração 'StringComparison' para executar comparações que não diferenciam maiúsculas de minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Prefira a sobrecarga do método de comparação de cadeia de '{0}' que usa um valor de enumeração 'StringComparison' para executar uma comparação que não diferencia maiúsculas de minúsculas + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Prefira as sobrecargas do método 'StringComparison' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Prefira as sobrecargas do método 'StringComparison' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas Use 'string.Equals(string, StringComparison)' - Usar 'string.Equals(string, StringComparison)' + Usar 'string.Equals(string, StringComparison)' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Evite chamar 'ToLower', 'ToUpper', 'ToLowerInvariant' e 'ToUpperInvariant' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas, como em 'string.ToLower() == string.ToLower()', porque elas levam a uma alocação. Em vez disso, use 'string.Equals(string, StringComparison)' para realizar comparações que não diferenciam maiúsculas de minúsculas. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Evite chamar 'ToLower', 'ToUpper', 'ToLowerInvariant' e 'ToUpperInvariant' para executar comparações de cadeia de caracteres que não diferenciam maiúsculas de minúsculas, como em 'string.ToLower() == string.ToLower()', porque elas levam a uma alocação. Em vez disso, use 'string.Equals(string, StringComparison)' para realizar comparações que não diferenciam maiúsculas de minúsculas. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Prefira usar 'string.Equals(cadeia de caracteres, StringComparison)' para realizar uma comparação que não diferencia maiúsculas de minúsculas + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefira usar 'string.Equals(cadeia de caracteres, StringComparison)' para realizar uma comparação que não diferencia maiúsculas de minúsculas 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 333c09d2c6..5b1ec3e803 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf @@ -2244,48 +2244,48 @@ Widening and user defined conversions are not supported with generic types. - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Избегайте вызова ToLower, ToUpper, ToLowerInvariant и ToUpperInvariant для сравнения строк без учета регистра при использовании CompareTo, так как они приведут к выделению. Вместо этого используйте StringComparer для сравнения без учета регистра. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Избегайте вызова ToLower, ToUpper, ToLowerInvariant и ToUpperInvariant для сравнения строк без учета регистра при использовании CompareTo, так как они приведут к выделению. Вместо этого используйте StringComparer для сравнения без учета регистра. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Используйте StringComparer для сравнения без учета регистра + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Используйте StringComparer для сравнения без учета регистра Use the 'string.{0}(string, StringComparison)' overload - Используйте перегрузку "string.{0}(string, StringComparison)" + Используйте перегрузку "string.{0}(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Избегайте вызова ToLower, ToUpper, ToLowerInvariant и ToUpperInvariant для сравнения строк без учета регистра, так как они приведут к выделению. Вместо этого вызывайте перегрузки методов Contains, IndexOf и StartsWith, которые принимают значение перечисления StringComparison для сравнения без учета регистра. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Используйте перегрузку метода сравнения строк "{0}", которая принимает значение перечисления StringComparison для сравнения без учета регистра + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Используйте перегрузки метода StringComparison для сравнения строк без учета регистра + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Используйте перегрузки метода StringComparison для сравнения строк без учета регистра Use 'string.Equals(string, StringComparison)' - Используйте "string.Equals(string, StringComparison)" + Используйте "string.Equals(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Избегайте вызовов "ToLower", "ToUpper", "ToLowerInvariant" и "ToUpperInvariant" для выполнения сравнения строк без учета регистра, как в "string.ToLower() == string.ToLower()", так как они приводят к распределению. Вместо этого используйте "string.Equals(string, StringComparison)" для выполнения сравнений без учета регистра. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Избегайте вызовов "ToLower", "ToUpper", "ToLowerInvariant" и "ToUpperInvariant" для выполнения сравнения строк без учета регистра, как в "string.ToLower() == string.ToLower()", так как они приводят к распределению. Вместо этого используйте "string.Equals(string, StringComparison)" для выполнения сравнений без учета регистра. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Предпочтительно использование "string.Equals(string, StringComparison)" для сравнения без чувствительностью к регистру + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Предпочтительно использование "string.Equals(string, StringComparison)" для сравнения без чувствительностью к регистру 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 f4700b6a05..a781602e5e 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf @@ -2244,48 +2244,48 @@ Genel türlerde genişletme ve kullanıcı tanımlı dönüştürmeler desteklen - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - Bir tahsise yol açtıkları için 'CompareTo' kullanırken büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'ToLower', 'ToUpper', 'ToLowerInvariant' ve 'ToUpperInvariant' çağırmaktan kaçının. Bunun yerine, büyük/küçük harfe duyarsız karşılaştırmalar yapmak için 'StringComparer' kullanın. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + Bir tahsise yol açtıkları için 'CompareTo' kullanırken büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'ToLower', 'ToUpper', 'ToLowerInvariant' ve 'ToUpperInvariant' çağırmaktan kaçının. Bunun yerine, büyük/küçük harfe duyarsız karşılaştırmalar yapmak için 'StringComparer' kullanın. - Prefer using 'StringComparer' to perform a case-insensitive comparison - Büyük/küçük harfe duyarlı olmayan bir karşılaştırma yapmak için 'StringComparer' kullanmayı tercih edin + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + Büyük/küçük harfe duyarlı olmayan bir karşılaştırma yapmak için 'StringComparer' kullanmayı tercih edin Use the 'string.{0}(string, StringComparison)' overload - 'string.{0}(string, StringComparison)' aşırı yüklemesini kullan + 'string.{0}(string, StringComparison)' aşırı yüklemesini kullan - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - Bir ayırmaya yol açtıkları için büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'ToLower', 'ToUpper', 'ToLowerInvariant' ve 'ToUpperInvariant' aramaktan kaçının. Bunun yerine, büyük/küçük harfe duyarsız karşılaştırmalar gerçekleştirmek için bir 'StringComparison' enum değeri alan 'Contains', 'IndexOf' ve 'StartsWith' yöntem aşırı yüklemelerini aramayı tercih edin. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - Büyük/küçük harfe duyarlı olmayan bir karşılaştırma gerçekleştirmek için bir 'StringComparison' enum değeri alan '{0}' dize karşılaştırma yöntemi aşırı yüklemesini tercih edin + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - Büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'StringComparison' metodu aşırı yüklemelerini tercih edin + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + Büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'StringComparison' metodu aşırı yüklemelerini tercih edin Use 'string.Equals(string, StringComparison)' - 'string.Equals(string, StringComparison)' parametresini kullanın + 'string.Equals(string, StringComparison)' parametresini kullanın - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - Bir ayrıma işlemine yol açtıkları için 'string.ToLower() == string.ToLower()' parametresinde olduğu gibi büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'ToLower', 'ToUpper', 'ToLowerInvariant' ve 'ToUpperInvariant' parametrelerini çağırmaktan kaçının. Bunun yerine, büyük/küçük harfe duyarsız karşılaştırmalar yapmak için 'string.Equals(string, StringComparison)' parametresini kullanın. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Bir ayrıma işlemine yol açtıkları için 'string.ToLower() == string.ToLower()' parametresinde olduğu gibi büyük/küçük harfe duyarsız dize karşılaştırmaları gerçekleştirmek için 'ToLower', 'ToUpper', 'ToLowerInvariant' ve 'ToUpperInvariant' parametrelerini çağırmaktan kaçının. Bunun yerine, büyük/küçük harfe duyarsız karşılaştırmalar yapmak için 'string.Equals(string, StringComparison)' parametresini kullanın. - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - Büyük/küçük harfe duyarsız karşılaştırma yapmak için 'string.Equals(string, StringComparison)' parametresini kullanmayı tercih edin + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Büyük/küçük harfe duyarsız karşılaştırma yapmak için 'string.Equals(string, StringComparison)' parametresini kullanmayı tercih edin 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 b9fc322c91..fa48390503 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 @@ -2244,48 +2244,48 @@ Enumerable.OfType<T> 使用的泛型类型检查 (C# 'is' operator/IL 'isi - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - 避免在使用 "CompareTo" 时调用"ToLower"、"ToUpper"、"ToLowerInvariant" 和 "ToUpperInvariant" 来执行不区分大小写的字符串比较,因为它们会导致分配。请使用 "StringComparer" 执行不区分大小写的比较。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + 避免在使用 "CompareTo" 时调用"ToLower"、"ToUpper"、"ToLowerInvariant" 和 "ToUpperInvariant" 来执行不区分大小写的字符串比较,因为它们会导致分配。请使用 "StringComparer" 执行不区分大小写的比较。 - Prefer using 'StringComparer' to perform a case-insensitive comparison - 首选使用“StringComparer”执行不区分大小写的比较 + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + 首选使用“StringComparer”执行不区分大小写的比较 Use the 'string.{0}(string, StringComparison)' overload - 使用 "string.{0}(string, StringComparison)" 重载 + 使用 "string.{0}(string, StringComparison)" 重载 - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - 避免调用 "ToLower"、"ToUpper"、"ToLowerInvariant" 和 "ToUpperInvariant" 来执行不区分大小写的字符串比较,因为它们会导致分配。相反,首选调用采用 "StringComparison" 枚举值的 "Contains"、"IndexOf" 和 "StartsWith" 的方法重载来执行不区分大小写的比较。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - 首选采用 "StringComparison" 枚举值来执行不区分大小写的比较的 "{0}" 的字符串比较方法重载 + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - 首选 "StringComparison" 方法重载来执行不区分大小写的字符串比较 + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + 首选 "StringComparison" 方法重载来执行不区分大小写的字符串比较 Use 'string.Equals(string, StringComparison)' - 使用 "string.Equals(string, StringComparison)" + 使用 "string.Equals(string, StringComparison)" - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - 就像在 "string.ToLower() == string.ToLower()" 中那样,避免调用 "ToLower"、"ToUpper"、"ToLowerInvariant" 和 "ToUpperInvariant" 来执行不区分大小写的字符串比较,因为它们会导致分配。请使用 "string.Equals(string, StringComparison)" 执行不区分大小写的比较。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + 就像在 "string.ToLower() == string.ToLower()" 中那样,避免调用 "ToLower"、"ToUpper"、"ToLowerInvariant" 和 "ToUpperInvariant" 来执行不区分大小写的字符串比较,因为它们会导致分配。请使用 "string.Equals(string, StringComparison)" 执行不区分大小写的比较。 - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - 首选使用 "string.Equals(string, StringComparison)" 来执行不区分大小写的比较 + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + 首选使用 "string.Equals(string, StringComparison)" 来执行不区分大小写的比较 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 09dc41c4fa..3262fb5e3c 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 @@ -2244,48 +2244,48 @@ Enumerable.OfType<T> 使用的一般型別檢查 (C# 'is' operator/IL 'isi - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. - 避免在使用 'CompareTo' 時呼叫 'ToLower'、'ToUpper'、'ToLowerInvariant' 和 'ToUpperInvariant' 來執行不區分大小寫的字串比較,因為它們會導致配置。請改用 'StringComparer' 來執行不區分大小寫的比較。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons when using 'CompareTo', because they lead to an allocation. Instead, use 'StringComparer' to perform case-insensitive comparisons. Switching to using 'StringComparer' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase'. + 避免在使用 'CompareTo' 時呼叫 'ToLower'、'ToUpper'、'ToLowerInvariant' 和 'ToUpperInvariant' 來執行不區分大小寫的字串比較,因為它們會導致配置。請改用 'StringComparer' 來執行不區分大小寫的比較。 - Prefer using 'StringComparer' to perform a case-insensitive comparison - 偏好使用 'StringComparer' 來執行不區分大小寫的比較 + Prefer using 'StringComparer' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparer.OrdinalIgnoreCase' + 偏好使用 'StringComparer' 來執行不區分大小寫的比較 Use the 'string.{0}(string, StringComparison)' overload - 使用 'string.{0}(string, StringComparison)' 多載 + 使用 'string.{0}(string, StringComparison)' 多載 - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. - 避免呼叫 'ToLower'、'ToUpper'、'ToLowerInvariant' 和 'ToUpperInvariant' 來執行不區分大小寫的字串比較,因為它們會導致配置。相反地,偏好呼叫採用 'StringComparison' 列舉值的 'Contains'、'IndexOf' 和 'StartsWith' 方法多載,以執行不區分大小寫的比較。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. - Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison - 偏好採用 'StringComparison' 列舉值之 '{0}' 的字串比較方法多載,以執行不區分大小寫的比較 + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + Prefer the string comparison method overload of '{0}' that takes a 'StringComparison' enum value to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' - Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons - 偏好使用 'StringComparison' 方法多載來執行不區分大小寫的字串比較 + Use the 'StringComparison' method overloads to perform case-insensitive string comparisons + 偏好使用 'StringComparison' 方法多載來執行不區分大小寫的字串比較 Use 'string.Equals(string, StringComparison)' - 使用 'string.Equals(string, StringComparison)' + 使用 'string.Equals(string, StringComparison)' - Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. - 如同在 'string.ToLower() == string.ToLower()' 中,避免呼叫 'ToLower'、'ToUpper'、'ToLowerInvariant' 和 'ToUpperInvariant' 來執行不區分大小寫的字串比較,因為它們會導致配置。請改用 'string.Equals(string, StringComparison)' 來執行不區分大小寫的比較。 + Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. + 如同在 'string.ToLower() == string.ToLower()' 中,避免呼叫 'ToLower'、'ToUpper'、'ToLowerInvariant' 和 'ToUpperInvariant' 來執行不區分大小寫的字串比較,因為它們會導致配置。請改用 'string.Equals(string, StringComparison)' 來執行不區分大小寫的比較。 - Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison - 建議使用 'string.Equals(string, StringComparison)' 執行不區分大小寫的比較 + Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase' + 建議使用 'string.Equals(string, StringComparison)' 執行不區分大小寫的比較 diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index 3679a4482a..97483bfac2 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -1704,9 +1704,9 @@ Constant arrays passed as arguments are not reused when called repeatedly, which |CodeFix|True| --- -## [CA1862](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862): Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons +## [CA1862](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862): Use the 'StringComparison' method overloads to perform case-insensitive string comparisons -Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. +Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'. |Item|Value| |-|-| diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index a8749e9830..3ab3fdbe1a 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -3214,8 +3214,8 @@ }, "CA1862": { "id": "CA1862", - "shortDescription": "Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons", - "fullDescription": "Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons.", + "shortDescription": "Use the 'StringComparison' method overloads to perform case-insensitive string comparisons", + "fullDescription": "Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons, as in 'string.ToLower() == string.ToLower()', because they lead to an allocation. Instead, use 'string.Equals(string, StringComparison)' to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'.", "defaultLevel": "note", "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862", "properties": { diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 42df726b08..c170a2f1ee 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -8,7 +8,7 @@ CA1512 | | Use ObjectDisposedException throw helper | CA1856 | | Incorrect usage of ConstantExpected attribute | CA1857 | | A constant is expected for the parameter | -CA1862 | | Prefer the 'StringComparison' method overloads to perform case-insensitive string comparisons | +CA1862 | | Use the 'StringComparison' method overloads to perform case-insensitive string comparisons | CA1863 | | Use 'CompositeFormat' | CA1865 | | Use char overload | CA1866 | | Use char overload | diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Base.Tests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Base.Tests.cs index 20db0a3391..63b590f0a2 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Base.Tests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Base.Tests.cs @@ -14,6 +14,18 @@ private static readonly (string, string)[] Cultures = new[] { ("ToUpperInvariant", "InvariantCultureIgnoreCase") }; + private static readonly (string, string)[] IncompatibleCaseChangingMethods = new[] + { + ("ToLower", "ToLowerInvariant"), + ("ToLower", "ToUpperInvariant"), + ("ToUpper", "ToLowerInvariant"), + ("ToUpper", "ToUpperInvariant"), + ("ToLowerInvariant", "ToLower"), + ("ToLowerInvariant", "ToUpper"), + ("ToUpperInvariant", "ToLower"), + ("ToUpperInvariant", "ToUpper"), + }; + private static readonly string[] ContainsStartsWith = new[] { "Contains", "StartsWith" }; private static readonly string[] UnnamedArgs = new[] { "", ", 1", ", 1, 1" }; @@ -29,13 +41,23 @@ private static readonly (string, string)[] VisualBasicComparisonOperators = new[ private const string CSharpSeparator = ": "; private const string VisualBasicSeparator = ":="; - private static string[] GetNamedArguments(string separator) => new string[] { - "", - $", startIndex{separator}1", - $", startIndex{separator}1, count{separator}1", - $", count{separator}1, startIndex{separator}1" + private static (string, string)[] GetNamedArguments(string separator) => new (string, string)[] { + ("", ""), + ($", startIndex{separator}1", $", startIndex{separator}1"), + ($", startIndex{separator}1, count{separator}1", $", startIndex{separator}1, count{separator}1") }; + // In C#, when the user names the arguments and passes them in a different order than the original, the fixer will + // be able to get the arguments from IInvocationOperation.Arguments in the order the user passed. + private static (string, string) CSharpIndexOfNamedArguments = new($", count: 1, startIndex: 1", $", count: 1, startIndex: 1"); + + // In VB, when the user names the arguments and passes them in a different order than the original, the fixer will + // not be able to get the arguments from IINvocation.Arguments in the order the user passed, and instead will + // get them in the original order as defined in the method signature. + private static (string, string) VisualBasicIndexOfNamedArguments = new($", count:=1, startIndex:=1", $", startIndex:=1, count:=1"); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is case-changed and the string argument is passed unmodified. public static IEnumerable DiagnosedAndFixedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -53,6 +75,8 @@ public static IEnumerable DiagnosedAndFixedData() } } + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is unmodified and the string argument is passed case-changed. public static IEnumerable DiagnosedAndFixedInvertedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -70,9 +94,12 @@ public static IEnumerable DiagnosedAndFixedInvertedData() } } - public static IEnumerable CSharpDiagnosedAndFixedNamedData() => DiagnosedAndFixedNamedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedNamedData() => DiagnosedAndFixedNamedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedNamedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedNamedData() => DiagnosedAndFixedNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedNamedData() => DiagnosedAndFixedNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is case-changed and the string argument is passed unmodified and explicitly named. + private static IEnumerable DiagnosedAndFixedNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { @@ -82,24 +109,50 @@ private static IEnumerable DiagnosedAndFixedNamedData(string separator } // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{arguments})", $"a.IndexOf(value{separator}b{arguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{originalArguments})", $"a.IndexOf(value{separator}b{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } } - public static IEnumerable DiagnosedAndFixedWithEqualsToData() + public static IEnumerable CSharpDiagnosedAndFixedInvertedNamedData() => DiagnosedAndFixedInvertedNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedInvertedNamedData() => DiagnosedAndFixedInvertedNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is unmodified and the string argument is passed case-changed and explicitly named. + private static IEnumerable DiagnosedAndFixedInvertedNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { foreach (string method in ContainsStartsWith) { - // Tests implicit boolean check - yield return new object[] { $"a.{caseChanging}().{method}(b)", $"a.{method}(b, StringComparison.{replacement})", "" }; + yield return new object[] { $"a.{method}(value{separator}b.{caseChanging}())", $"a.{method}(value{separator}b, comparisonType{separator}StringComparison.{replacement})" }; } - // Tests having an appended method invocation at the end + // IndexOf overloads + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) + { + yield return new object[] { $"a.IndexOf(value{separator}b.{caseChanging}(){originalArguments})", $"a.IndexOf(value{separator}b{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; + } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; + } + } + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is case-changed and the string argument is unmodified + // and the result of the method then calls another method. + public static IEnumerable DiagnosedAndFixedWithAppendedMethodData() + { + foreach ((string caseChanging, string replacement) in Cultures) + { + foreach (string method in ContainsStartsWith) + { + yield return new object[] { $"a.{caseChanging}().{method}(b)", $"a.{method}(b, StringComparison.{replacement})", ".Equals(myBoolean)" }; + } // IndexOf overloads foreach (string arguments in UnnamedArgs) @@ -109,18 +162,18 @@ public static IEnumerable DiagnosedAndFixedWithEqualsToData() } } - public static IEnumerable DiagnosedAndFixedWithEqualsToInvertedData() + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is unmodified and the string argument is case-changed + // and the result of the method then calls another method. + public static IEnumerable DiagnosedAndFixedWithAppendedMethodInvertedData() { foreach ((string caseChanging, string replacement) in Cultures) { foreach (string method in ContainsStartsWith) { - // Tests implicit boolean check - yield return new object[] { $"a.{method}(b.{caseChanging}())", $"a.{method}(b, StringComparison.{replacement})", "" }; + yield return new object[] { $"a.{method}(b.{caseChanging}())", $"a.{method}(b, StringComparison.{replacement})", ".Equals(myBoolean)" }; } - // Tests having an appended method invocation at the end - // IndexOf overloads foreach (string arguments in UnnamedArgs) { @@ -129,28 +182,53 @@ public static IEnumerable DiagnosedAndFixedWithEqualsToInvertedData() } } - public static IEnumerable CSharpDiagnosedAndFixedWithEqualsToNamedData() => DiagnosedAndFixedWithEqualsToNamedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedWithEqualsToNamedData() => DiagnosedAndFixedWithEqualsToNamedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedWithEqualsToNamedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedWithAppendedMethodNamedData() => DiagnosedAndFixedWithAppendedMethodNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedWithAppendedMethodNamedData() => DiagnosedAndFixedWithAppendedMethodNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is case-changed and the string argument is unmodified and explicitly named + // and the result of the method then calls another method. + private static IEnumerable DiagnosedAndFixedWithAppendedMethodNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { foreach (string method in ContainsStartsWith) { - // Tests implicit boolean check - yield return new object[] { $"a.{caseChanging}().{method}(value{separator}b)", $"a.{method}(value{separator}b, comparisonType{separator}StringComparison.{replacement})", "" }; + yield return new object[] { $"a.{caseChanging}().{method}(value{separator}b)", $"a.{method}(value{separator}b, comparisonType{separator}StringComparison.{replacement})", ".Equals(myBoolean)" }; } - // Tests having an appended method invocation at the end - // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{arguments})", $"a.IndexOf(value{separator}b{arguments}, comparisonType{separator}StringComparison.{replacement})", ".Equals(-1)" }; + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{originalArguments})", $"a.IndexOf(value{separator}b{expectedArguments}, comparisonType{separator}StringComparison.{replacement})", ".Equals(-1)" }; } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})", ".Equals(-1)" }; } } + // Test cases for Contains, StartsWith + // where the instance string is case-changed and the string argument is unmodified + // and the boolean result is consumed in a condition statement. + public static IEnumerable DiagnosedAndFixedImplicitBooleanData() + { + foreach ((string caseChanging, string replacement) in Cultures) + { + foreach (string method in ContainsStartsWith) + { + yield return new object[] { $"a.{caseChanging}().{method}(b)", $"a.{method}(b, StringComparison.{replacement})", "" }; + } + + // Inverted + foreach (string method in ContainsStartsWith) + { + yield return new object[] { $"a.{method}(b.{caseChanging}())", $"a.{method}(b, StringComparison.{replacement})", "" }; + } + } + } + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is a case-changed literal and the string argument is an unmodified string literal. public static IEnumerable DiagnosedAndFixedStringLiteralsData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -168,6 +246,8 @@ public static IEnumerable DiagnosedAndFixedStringLiteralsData() } } + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is an unmodified literal and the string argument is a case-changed string literal. public static IEnumerable DiagnosedAndFixedStringLiteralsInvertedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -185,9 +265,12 @@ public static IEnumerable DiagnosedAndFixedStringLiteralsInvertedData( } } - public static IEnumerable CSharpDiagnosedAndFixedStringLiteralsNamedData() => DiagnosedAndFixedStringLiteralsNamedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedStringLiteralsNamedData() => DiagnosedAndFixedStringLiteralsNamedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedStringLiteralsNamedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedStringLiteralsNamedData() => DiagnosedAndFixedStringLiteralsNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedStringLiteralsNamedData() => DiagnosedAndFixedStringLiteralsNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is a case-changed literal and the string argument is an unmodified, explicitly named string literal. + private static IEnumerable DiagnosedAndFixedStringLiteralsNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { @@ -197,13 +280,41 @@ private static IEnumerable DiagnosedAndFixedStringLiteralsNamedData(st } // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) + { + yield return new object[] { $"\"aBc\".{caseChanging}().IndexOf(value{separator}\"CdE\"{originalArguments})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; + } + + yield return new object[] { $"\"aBc\".{caseChanging}().IndexOf(value{separator}\"CdE\"{langSpecificOrderedNamedArgs.Item1})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; + } + } + + public static IEnumerable CSharpDiagnosedAndFixedStringLiteralsInvertedNamedData() => DiagnosedAndFixedStringLiteralsInvertedNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedStringLiteralsInvertedNamedData() => DiagnosedAndFixedStringLiteralsInvertedNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is an unmodified literal and the string argument is a case-changed, explicitly named string literal. + private static IEnumerable DiagnosedAndFixedStringLiteralsInvertedNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) + { + foreach ((string caseChanging, string replacement) in Cultures) + { + foreach (string method in ContainsStartsWith) + { + yield return new object[] { $"\"aBc\".{method}(value{separator}\"CdE\".{caseChanging}())", $"\"aBc\".{method}(value{separator}\"CdE\", comparisonType{separator}StringComparison.{replacement})" }; + } + + // IndexOf overloads + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"\"aBc\".{caseChanging}().IndexOf(value{separator}\"CdE\"{arguments})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{arguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"\"aBc\".IndexOf(value{separator}\"CdE\".{caseChanging}(){originalArguments})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"\"aBc\".{caseChanging}().IndexOf(value{separator}\"CdE\"{langSpecificOrderedNamedArgs.Item1})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } } + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is a method invocation that is case-changed, and the string argument is unmodified and comes from another method invocation. public static IEnumerable DiagnosedAndFixedStringReturningMethodsData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -221,6 +332,8 @@ public static IEnumerable DiagnosedAndFixedStringReturningMethodsData( } } + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is a method invocation and is unmodified, and the string argument is case-changed and comes from another method invocation. public static IEnumerable DiagnosedAndFixedStringReturningMethodsInvertedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -238,9 +351,12 @@ public static IEnumerable DiagnosedAndFixedStringReturningMethodsInver } } - public static IEnumerable CSharpDiagnosedAndFixedStringReturningMethodsNamedData() => DiagnosedAndFixedStringReturningMethodsNamedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedStringReturningMethodsNamedData() => DiagnosedAndFixedStringReturningMethodsNamedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedStringReturningMethodsNamedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedStringReturningMethodsNamedData() => DiagnosedAndFixedStringReturningMethodsNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedStringReturningMethodsNamedData() => DiagnosedAndFixedStringReturningMethodsNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is a method invocation that is case-changed, and the string argument is unmodified, comes from another method invocation, and is explicitly named. + private static IEnumerable DiagnosedAndFixedStringReturningMethodsNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { @@ -250,13 +366,41 @@ private static IEnumerable DiagnosedAndFixedStringReturningMethodsName } // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"GetStringA().{caseChanging}().IndexOf(value{separator}GetStringB(){arguments})", $"GetStringA().IndexOf(value{separator}GetStringB(){arguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"GetStringA().{caseChanging}().IndexOf(value{separator}GetStringB(){originalArguments})", $"GetStringA().IndexOf(value{separator}GetStringB(){expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"GetStringA().{caseChanging}().IndexOf(value{separator}GetStringB(){langSpecificOrderedNamedArgs.Item1})", $"GetStringA().IndexOf(value{separator}GetStringB(){langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } } + public static IEnumerable CSharpDiagnosedAndFixedStringReturningMethodsInvertedNamedData() => DiagnosedAndFixedStringReturningMethodsInvertedNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedStringReturningMethodsInvertedNamedData() => DiagnosedAndFixedStringReturningMethodsInvertedNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the instance string is unmodified and comes from a method invocation, and the string argument is case-changed, comes from another method invocation, and is explicitly named. + private static IEnumerable DiagnosedAndFixedStringReturningMethodsInvertedNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) + { + foreach ((string caseChanging, string replacement) in Cultures) + { + foreach (string method in ContainsStartsWith) + { + yield return new object[] { $"GetStringA().{method}(value{separator}GetStringB().{caseChanging}())", $"GetStringA().{method}(value{separator}GetStringB(), comparisonType{separator}StringComparison.{replacement})" }; + } + + // IndexOf overloads + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) + { + yield return new object[] { $"GetStringA().IndexOf(value{separator}GetStringB().{caseChanging}(){originalArguments})", $"GetStringA().IndexOf(value{separator}GetStringB(){expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; + } + + yield return new object[] { $"GetStringA().{caseChanging}().IndexOf(value{separator}GetStringB(){langSpecificOrderedNamedArgs.Item1})", $"GetStringA().IndexOf(value{separator}GetStringB(){langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; + } + } + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the case-changed invocation string literal is enclosed in parenthesis, and the argument is another string literal. public static IEnumerable DiagnosedAndFixedParenthesizedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -274,6 +418,8 @@ public static IEnumerable DiagnosedAndFixedParenthesizedData() } } + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the invocation is a string literal and the argument is a case-changed string literal enclosed in parenthesis. public static IEnumerable DiagnosedAndFixedParenthesizedInvertedData() { foreach ((string caseChanging, string replacement) in Cultures) @@ -291,85 +437,84 @@ public static IEnumerable DiagnosedAndFixedParenthesizedInvertedData() } } - public static IEnumerable CSharpDiagnosedAndFixedParenthesizedNamedData() => DiagnosedAndFixedParenthesizedNamedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedParenthesizedNamedData() => DiagnosedAndFixedParenthesizedNamedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedParenthesizedNamedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedParenthesizedNamedData() => DiagnosedAndFixedParenthesizedNamedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedParenthesizedNamedData() => DiagnosedAndFixedParenthesizedNamedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the case-changed invocation string literal is enclosed in parenthesis, and the argument is another string literal, explicitly named. + private static IEnumerable DiagnosedAndFixedParenthesizedNamedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { foreach (string method in ContainsStartsWith) { yield return new object[] { $"(\"aBc\".{caseChanging}()).{method}(value{separator}\"CdE\")", $"\"aBc\".{method}(value{separator}\"CdE\", comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"(GetString().{caseChanging}()).{method}(value{separator}GetString())", $"GetString().{method}(value{separator}GetString(), comparisonType{separator}StringComparison.{replacement})" }; } // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"(\"aBc\".{caseChanging}()).IndexOf(value{separator}\"CdE\"{arguments})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{arguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"(\"aBc\".{caseChanging}()).IndexOf(value{separator}\"CdE\"{originalArguments})", $"\"aBc\".IndexOf(value{separator}\"CdE\"{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"(GetString().{caseChanging}()).IndexOf(value{separator}GetString(){originalArguments})", $"GetString().IndexOf(value{separator}GetString(){expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } } - public static IEnumerable CSharpDiagnosedAndFixedParenthesizedNamedInvertedData() => DiagnosedAndFixedParenthesizedNamedInvertedData(CSharpSeparator); - public static IEnumerable VisualBasicDiagnosedAndFixedParenthesizedNamedInvertedData() => DiagnosedAndFixedParenthesizedNamedInvertedData(VisualBasicSeparator); - private static IEnumerable DiagnosedAndFixedParenthesizedNamedInvertedData(string separator) + public static IEnumerable CSharpDiagnosedAndFixedParenthesizedNamedInvertedData() => DiagnosedAndFixedParenthesizedNamedInvertedData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedParenthesizedNamedInvertedData() => DiagnosedAndFixedParenthesizedNamedInvertedData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the invocation is a string literal and the argument is a case-changed string literal enclosed in parenthesis and explicitly named. + private static IEnumerable DiagnosedAndFixedParenthesizedNamedInvertedData(string separator, (string, string) langSpecificOrderedNamedArgs) { foreach ((string caseChanging, string replacement) in Cultures) { foreach (string method in ContainsStartsWith) { + yield return new object[] { $"(\"aBc\").{method}(value{separator}(\"cDe\".{caseChanging}()))", $"(\"aBc\").{method}(value{separator}\"cDe\", comparisonType{separator}StringComparison.{replacement})" }; yield return new object[] { $"(GetString()).{method}(value{separator}(GetString().{caseChanging}()))", $"(GetString()).{method}(value{separator}GetString(), comparisonType{separator}StringComparison.{replacement})" }; } // IndexOf overloads - foreach (string arguments in GetNamedArguments(separator)) + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) { - yield return new object[] { $"(GetString()).IndexOf(value{separator}(GetString().{caseChanging}()){arguments})", $"(GetString()).IndexOf(value{separator}GetString(){arguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"(\"aBc\").IndexOf(value{separator}(\"cDe\".{caseChanging}()){originalArguments})", $"(\"aBc\").IndexOf(value{separator}\"cDe\"{expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"(GetString()).IndexOf(value{separator}(GetString().{caseChanging}()){originalArguments})", $"(GetString()).IndexOf(value{separator}GetString(){expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } } - public static IEnumerable CSharpDiagnosedAndFixedEqualityToEqualsData() => - DiagnosedAndFixedEqualityToEqualsData(CSharpComparisonOperators); - public static IEnumerable VisualBasicDiagnosedAndFixedEqualityToEqualsData() => - DiagnosedAndFixedEqualityToEqualsData(VisualBasicComparisonOperators); - private static IEnumerable DiagnosedAndFixedEqualityToEqualsData(ValueTuple[] comparisonOperators) + public static IEnumerable CSharpDiagnosedAndFixedParenthesizedComplexCasesData() => DiagnosedAndFixedParenthesizedComplexCasesData(CSharpSeparator, CSharpIndexOfNamedArguments); + public static IEnumerable VisualBasicDiagnosedAndFixedParenthesizedComplexCasesData() => DiagnosedAndFixedParenthesizedComplexCasesData(VisualBasicSeparator, VisualBasicIndexOfNamedArguments); + + // Test cases for Contains, StartsWith and all overloads of IndexOf + // where the invocation and the argument are both enclosed in various combinations of parenthesis. + private static IEnumerable DiagnosedAndFixedParenthesizedComplexCasesData(string separator, (string, string) langSpecificOrderedNamedArgs) { -#pragma warning disable format - foreach (string casing in new[]{ "Lower", "Upper" }) + foreach ((string caseChanging, string replacement) in Cultures) { - foreach ((string before, string after) in comparisonOperators) + foreach (string method in ContainsStartsWith) { - yield return new object[] { $"a.To{casing}() {before} b.To{casing}()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}() {before} b.To{casing}Invariant()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}() {before} \"abc\"", $"{after}a.Equals(\"abc\", StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}() {before} b", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - - yield return new object[] { $"a.To{casing}Invariant() {before} b.To{casing}Invariant()", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}Invariant() {before} b.To{casing}()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}Invariant() {before} \"abc\"", $"{after}a.Equals(\"abc\", StringComparison.InvariantCultureIgnoreCase)" }; - yield return new object[] { $"a.To{casing}Invariant() {before} b", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; - - yield return new object[] { $"a {before} b.To{casing}()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"a {before} b.To{casing}Invariant()", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; - - yield return new object[] { $"\"abc\" {before} b.To{casing}()", $"{after}\"abc\".Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"\"abc\" {before} b.To{casing}Invariant()", $"{after}\"abc\".Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; - yield return new object[] { $"\"abc\".To{casing}() {before} b.To{casing}()", $"{after}\"abc\".Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"\"abc\".To{casing}() {before} b.To{casing}Invariant()", $"{after}\"abc\".Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"\"abc\".To{casing}Invariant() {before} b.To{casing}Invariant()", $"{after}\"abc\".Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + yield return new object[] { $"((GetString().{caseChanging}())).{method}(value{separator}((GetString().{caseChanging}())))", $"GetString().{method}(value{separator}GetString(), comparisonType{separator}StringComparison.{replacement})" }; + yield return new object[] { $"((a.{caseChanging}())).{method}(value{separator}((b.{caseChanging}())))", $"a.{method}(value{separator}b, comparisonType{separator}StringComparison.{replacement})" }; + } - yield return new object[] { $"GetString().To{casing}() {before} a.To{casing}()", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"GetString().To{casing}() {before} a.To{casing}Invariant()", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"GetString().To{casing}Invariant() {before} a.To{casing}()", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"GetString().To{casing}() {before} a", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; - yield return new object[] { $"GetString().To{casing}Invariant() {before} a", $"{after}GetString().Equals(a, StringComparison.InvariantCultureIgnoreCase)" }; - yield return new object[] { $"GetString().To{casing}Invariant() {before} \"abc\"", $"{after}GetString().Equals(\"abc\", StringComparison.InvariantCultureIgnoreCase)" }; + // IndexOf overloads + foreach ((string originalArguments, string expectedArguments) in GetNamedArguments(separator)) + { + yield return new object[] { $"((GetString().{caseChanging}())).IndexOf(value{separator}((GetString().{caseChanging}())){originalArguments})", $"GetString().IndexOf(value{separator}GetString(){expectedArguments}, comparisonType{separator}StringComparison.{replacement})" }; } + + yield return new object[] { $"a.{caseChanging}().IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item1})", $"a.IndexOf(value{separator}b{langSpecificOrderedNamedArgs.Item2}, comparisonType{separator}StringComparison.{replacement})" }; } -#pragma warning restore format } + // Variety of test cases that should not emit a diagnostic. public static IEnumerable NoDiagnosticData() { // Test needs to define a char ch and an object obj @@ -397,6 +542,32 @@ public static IEnumerable NoDiagnosticData() yield return new object[] { "\"aBc\".CompareTo(\"cDe\")" }; } + public static IEnumerable DiagnosticNoFixStartsWithContainsIndexOfData() + { + foreach ((string left, string right) in IncompatibleCaseChangingMethods) + { + yield return new object[] { $"a.{left}().StartsWith(b.{right}())" }; + yield return new object[] { $"a.{left}().Contains(b.{right}())" }; + yield return new object[] { $"\"aBc\".{left}().StartsWith(\"cDe\".{right}())" }; + yield return new object[] { $"\"aBc\".{left}().Contains(\"cDe\".{right}())" }; + yield return new object[] { $"GetStringA().{left}().StartsWith(GetStringB().{right}())" }; + yield return new object[] { $"GetStringA().{left}().Contains(GetStringB().{right}())" }; + + yield return new object[] { $"a.{left}().StartsWith(b.{right}())" }; + yield return new object[] { $"a.{left}().Contains(b.{right}())" }; + yield return new object[] { $"\"aBc\".{left}().StartsWith(\"cDe\".{right}())" }; + yield return new object[] { $"\"aBc\".{left}().Contains(\"cDe\".{right}())" }; + + // IndexOf overloads + foreach (string arguments in UnnamedArgs) + { + yield return new object[] { $"a.{left}().IndexOf(b.{right}(){arguments})" }; + yield return new object[] { $"a.{left}().IndexOf(b.{right}(){arguments})" }; + } + } + } + + // Test cases for CompareTo, with the invocation string case-changed, that should emit a diagnostic but should not offer a fix. public static IEnumerable DiagnosticNoFixCompareToData() { // Tests need to define strings a, b, and methods GetStringA, GetStringB @@ -409,25 +580,7 @@ public static IEnumerable DiagnosticNoFixCompareToData() } } - public static IEnumerable CSharpDiagnosticNoFixEqualsData() => DiagnosticNoFixEqualsData(CSharpComparisonOperators); - public static IEnumerable VisualBasicDiagnosticNoFixEqualsData() => DiagnosticNoFixEqualsData(VisualBasicComparisonOperators); - - private static IEnumerable DiagnosticNoFixEqualsData(ValueTuple[] ops) - { - foreach ((string op, _) in ops) - { - yield return new object[] { $"\"aBc\".ToLower() {op} \"cDe\".ToLowerInvariant()" }; - yield return new object[] { $"\"aBc\".ToLower() {op} \"cDe\".ToUpperInvariant()" }; - yield return new object[] { $"\"aBc\".ToUpper() {op} \"cDe\".ToLowerInvariant()" }; - yield return new object[] { $"\"aBc\".ToUpper() {op} \"cDe\".ToUpperInvariant()" }; - - yield return new object[] { $"\"aBc\".ToLowerInvariant() {op} \"cDe\".ToLower()" }; - yield return new object[] { $"\"aBc\".ToLowerInvariant() {op} \"cDe\".ToUpper()" }; - yield return new object[] { $"\"aBc\".ToUpperInvariant() {op} \"cDe\".ToLower()" }; - yield return new object[] { $"\"aBc\".ToUpperInvariant() {op} \"cDe\".ToUpper()" }; - } - } - + // Test cases for CompareTo, with the argument string case-changed, that should emit a diagnostic but should not offer a fix. public static IEnumerable DiagnosticNoFixCompareToInvertedData() { // Tests need to define strings a, b, and methods GetStringA, GetStringB @@ -442,6 +595,9 @@ public static IEnumerable DiagnosticNoFixCompareToInvertedData() public static IEnumerable CSharpDiagnosticNoFixCompareToNamedData() => DiagnosticNoFixCompareToNamedData(CSharpSeparator); public static IEnumerable VisualBasicDiagnosticNoFixCompareToNamedData() => DiagnosticNoFixCompareToNamedData(VisualBasicSeparator); + + // Test cases for CompareTo, with the invocation string case-changed and the argument string explicitly named, + // that should emit a diagnostic but should not offer a fix. private static IEnumerable DiagnosticNoFixCompareToNamedData(string separator) { // Tests need to define strings a, b @@ -449,11 +605,94 @@ private static IEnumerable DiagnosticNoFixCompareToNamedData(string se { yield return new object[] { $"a.{caseChanging}().CompareTo(strB{separator}b)" }; yield return new object[] { $"(\"aBc\".{caseChanging}()).CompareTo(strB{separator}\"CdE\")" }; + } + } - // Inverted + public static IEnumerable CSharpDiagnosticNoFixCompareToInvertedNamedData() => DiagnosticNoFixCompareToInvertedNamedData(CSharpSeparator); + public static IEnumerable VisualBasicDiagnosticNoFixCompareToInvertedNamedData() => DiagnosticNoFixCompareToInvertedNamedData(VisualBasicSeparator); + + // Test cases for CompareTo, with the invocation string unmodified and the argument string case-changed and explicitly named, + // that should emit a diagnostic but should not offer a fix. + private static IEnumerable DiagnosticNoFixCompareToInvertedNamedData(string separator) + { + // Tests need to define strings a, b + foreach ((string caseChanging, _) in Cultures) + { yield return new object[] { $"a.CompareTo(strB{separator}b.{caseChanging}())" }; yield return new object[] { $"(\"aBc\").CompareTo(strB{separator}\"CdE\".{caseChanging}())" }; } } + + public static IEnumerable CSharpDiagnosedAndFixedEqualityToEqualsData() => + DiagnosedAndFixedEqualityToEqualsData(CSharpComparisonOperators); + public static IEnumerable VisualBasicDiagnosedAndFixedEqualityToEqualsData() => + DiagnosedAndFixedEqualityToEqualsData(VisualBasicComparisonOperators); + + // Test cases for string equality binary operations with one side being case-changed, + // or both sides being case-changed to the same culture. + private static IEnumerable DiagnosedAndFixedEqualityToEqualsData(ValueTuple[] comparisonOperators) + { +#pragma warning disable format + foreach (string casing in new[]{ "Lower", "Upper" }) + { + foreach ((string before, string after) in comparisonOperators) + { + yield return new object[] { $"a.To{casing}() {before} b.To{casing}()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"a.To{casing}() {before} \"abc\"", $"{after}a.Equals(\"abc\", StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"a.To{casing}() {before} b", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; + + yield return new object[] { $"a.To{casing}Invariant() {before} b.To{casing}Invariant()", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + yield return new object[] { $"a.To{casing}Invariant() {before} \"abc\"", $"{after}a.Equals(\"abc\", StringComparison.InvariantCultureIgnoreCase)" }; + yield return new object[] { $"a.To{casing}Invariant() {before} b", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + + yield return new object[] { $"a {before} b.To{casing}()", $"{after}a.Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"a {before} b.To{casing}Invariant()", $"{after}a.Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + + yield return new object[] { $"\"abc\" {before} b.To{casing}()", $"{after}\"abc\".Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"\"abc\" {before} b.To{casing}Invariant()", $"{after}\"abc\".Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + yield return new object[] { $"\"abc\".To{casing}() {before} b.To{casing}()", $"{after}\"abc\".Equals(b, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"\"abc\".To{casing}Invariant() {before} b.To{casing}Invariant()", $"{after}\"abc\".Equals(b, StringComparison.InvariantCultureIgnoreCase)" }; + + yield return new object[] { $"GetString().To{casing}() {before} a.To{casing}()", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"GetString().To{casing}() {before} a", $"{after}GetString().Equals(a, StringComparison.CurrentCultureIgnoreCase)" }; + yield return new object[] { $"GetString().To{casing}Invariant() {before} a", $"{after}GetString().Equals(a, StringComparison.InvariantCultureIgnoreCase)" }; + yield return new object[] { $"GetString().To{casing}Invariant() {before} \"abc\"", $"{after}GetString().Equals(\"abc\", StringComparison.InvariantCultureIgnoreCase)" }; + } + } +#pragma warning restore format + } + + public static IEnumerable CSharpDiagnosticNoFixEqualsData() => DiagnosticNoFixEqualsData(CSharpComparisonOperators); + public static IEnumerable VisualBasicDiagnosticNoFixEqualsData() => DiagnosticNoFixEqualsData(VisualBasicComparisonOperators); + + // Test cases for string equality binary operations that should emit a diagnostic but should not offer a fix + // because both sides are getting case-changed with different culture. + private static IEnumerable DiagnosticNoFixEqualsData(ValueTuple[] comparisonOperators) + { + foreach ((string op, _) in comparisonOperators) + { + foreach (string casing in new[] { "Lower", "Upper" }) + { + yield return new object[] { $"a.To{casing}() {op} b.To{casing}Invariant()" }; + yield return new object[] { $"\"abc\".To{casing}() {op} b.To{casing}Invariant()" }; + yield return new object[] { $"GetString().To{casing}() {op} a.To{casing}Invariant()" }; + + yield return new object[] { $"a.To{casing}Invariant() {op} b.To{casing}()" }; + yield return new object[] { $"\"abc\".To{casing}Invariant() {op} b.To{casing}()" }; + yield return new object[] { $"GetString().To{casing}Invariant() {op} a.To{casing}()" }; + } + + yield return new object[] { $"\"aBc\".ToLower() {op} \"cDe\".ToLowerInvariant()" }; + yield return new object[] { $"\"aBc\".ToLower() {op} \"cDe\".ToUpperInvariant()" }; + yield return new object[] { $"\"aBc\".ToUpper() {op} \"cDe\".ToLowerInvariant()" }; + yield return new object[] { $"\"aBc\".ToUpper() {op} \"cDe\".ToUpperInvariant()" }; + + yield return new object[] { $"\"aBc\".ToLowerInvariant() {op} \"cDe\".ToLower()" }; + yield return new object[] { $"\"aBc\".ToLowerInvariant() {op} \"cDe\".ToUpper()" }; + yield return new object[] { $"\"aBc\".ToUpperInvariant() {op} \"cDe\".ToLower()" }; + yield return new object[] { $"\"aBc\".ToUpperInvariant() {op} \"cDe\".ToUpper()" }; + + } + } } } \ No newline at end of file diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs index e068602645..bea4a72791 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs @@ -15,6 +15,7 @@ public class RecommendCaseInsensitiveStringComparison_CSharp_Tests : RecommendCa [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedNamedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_Assign(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -44,6 +45,7 @@ void M() [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedNamedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_Return(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -70,10 +72,11 @@ object M() } [Theory] - [MemberData(nameof(DiagnosedAndFixedWithEqualsToData))] - [MemberData(nameof(DiagnosedAndFixedWithEqualsToInvertedData))] - [MemberData(nameof(CSharpDiagnosedAndFixedWithEqualsToNamedData))] - public async Task Diagnostic_If(string diagnosedLine, string fixedLine, string equalsTo) + [MemberData(nameof(DiagnosedAndFixedImplicitBooleanData))] + [MemberData(nameof(DiagnosedAndFixedWithAppendedMethodData))] + [MemberData(nameof(DiagnosedAndFixedWithAppendedMethodInvertedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedWithAppendedMethodNamedData))] + public async Task Diagnostic_If(string diagnosedLine, string fixedLine, string appendedMethod) { string originalCode = $@"using System; class C @@ -82,7 +85,8 @@ int M() {{ string a = ""aBc""; string b = ""bc""; - if ([|{diagnosedLine}|]{equalsTo}) + bool myBoolean = false; + if ([|{diagnosedLine}|]{appendedMethod}) {{ return 5; }} @@ -96,7 +100,8 @@ int M() {{ string a = ""aBc""; string b = ""bc""; - if ({fixedLine}{equalsTo}) + bool myBoolean = false; + if ({fixedLine}{appendedMethod}) {{ return 5; }} @@ -110,6 +115,7 @@ int M() [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedNamedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_IgnoreResult(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -139,6 +145,7 @@ void M() [MemberData(nameof(DiagnosedAndFixedStringLiteralsData))] [MemberData(nameof(DiagnosedAndFixedStringLiteralsInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedStringLiteralsNamedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedStringLiteralsInvertedNamedData))] public async Task Diagnostic_StringLiterals_ReturnExpressionBody(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -158,6 +165,7 @@ class C [MemberData(nameof(DiagnosedAndFixedStringReturningMethodsData))] [MemberData(nameof(DiagnosedAndFixedStringReturningMethodsInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedStringReturningMethodsNamedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedStringReturningMethodsInvertedNamedData))] public async Task Diagnostic_StringReturningMethods_Discard(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -188,6 +196,7 @@ void M() [MemberData(nameof(DiagnosedAndFixedParenthesizedInvertedData))] [MemberData(nameof(CSharpDiagnosedAndFixedParenthesizedNamedData))] [MemberData(nameof(CSharpDiagnosedAndFixedParenthesizedNamedInvertedData))] + [MemberData(nameof(CSharpDiagnosedAndFixedParenthesizedComplexCasesData))] public async Task Diagnostic_Parenthesized_ReturnCastedToString(string diagnosedLine, string fixedLine) { string originalCode = $@"using System; @@ -196,6 +205,8 @@ class C string GetString() => ""aBc""; string M() {{ + string a = ""aBc""; + string b = ""cDe""; return ([|{diagnosedLine}|]).ToString(); }} }}"; @@ -205,6 +216,8 @@ class C string GetString() => ""aBc""; string M() {{ + string a = ""aBc""; + string b = ""cDe""; return ({fixedLine}).ToString(); }} }}"; @@ -249,9 +262,9 @@ class C bool M(string a, string b) {{ // Trivia - bool /* Trivia */ result = /* Trivia */ [|a.ToLower() // Trivia + bool /* Trivia */ result = /* Trivia */ [|a.ToLowerInvariant() // Trivia == /* Trivia */ b.ToLowerInvariant()|] /* Trivia */; // Trivia - if (/* Trivia */ [|a.ToLowerInvariant() /* Trivia */ != /* Trivia */ b.ToLower()|] /* Trivia */) // Trivia + if (/* Trivia */ [|a.ToLower() /* Trivia */ != /* Trivia */ b.ToLower()|] /* Trivia */) // Trivia return /* Trivia */ [|b /* Trivia */ != /* Trivia */ a.ToLowerInvariant()|] /* Trivia */; // Trivia return // Trivia [|""abc"" /* Trivia */ == /* Trivia */ a.ToUpperInvariant()|] /* Trivia */; // Trivia @@ -264,7 +277,7 @@ class C bool M(string a, string b) {{ // Trivia - bool /* Trivia */ result = /* Trivia */ a.Equals(b, StringComparison.CurrentCultureIgnoreCase) /* Trivia */; // Trivia + bool /* Trivia */ result = /* Trivia */ a.Equals(b, StringComparison.InvariantCultureIgnoreCase) /* Trivia */; // Trivia if (/* Trivia */ !a.Equals(b, StringComparison.CurrentCultureIgnoreCase) /* Trivia */) // Trivia return /* Trivia */ !b /* Trivia */ .Equals /* Trivia */ (a, StringComparison.InvariantCultureIgnoreCase) /* Trivia */; // Trivia return // Trivia @@ -297,10 +310,30 @@ object M() await VerifyNoDiagnosticCSharpAsync(originalCode); } + [Theory] + [MemberData(nameof(DiagnosticNoFixStartsWithContainsIndexOfData))] + public async Task Diagnostic_NoFix_StartsWithContainsIndexOf(string diagnosedLine) + { + string originalCode = $@"using System; +class C +{{ + string GetStringA() => ""aBc""; + string GetStringB() => ""cDe""; + object M() + {{ + string a = ""AbC""; + string b = ""CdE""; + return [|{diagnosedLine}|]; + }} +}}"; + await VerifyFixCSharpAsync(originalCode, originalCode); + } + [Theory] [MemberData(nameof(DiagnosticNoFixCompareToData))] [MemberData(nameof(DiagnosticNoFixCompareToInvertedData))] [MemberData(nameof(CSharpDiagnosticNoFixCompareToNamedData))] + [MemberData(nameof(CSharpDiagnosticNoFixCompareToInvertedNamedData))] public async Task Diagnostic_NoFix_CompareTo(string diagnosedLine) { string originalCode = $@"using System; @@ -315,7 +348,7 @@ int M() return [|{diagnosedLine}|]; }} }}"; - await VerifyDiagnosticOnlyCSharpAsync(originalCode); + await VerifyFixCSharpAsync(originalCode, originalCode); } [Theory] @@ -325,13 +358,16 @@ public async Task Diagnostic_NoFix_Equals(string diagnosedLine) string originalCode = $@"using System; class C {{ + string GetString() => string.Empty; bool M() {{ + string a = ""aBc""; + string b = ""dEf""; return [|{diagnosedLine}|]; }} }}"; - await VerifyDiagnosticOnlyCSharpAsync(originalCode); + await VerifyFixCSharpAsync(originalCode, originalCode); } private async Task VerifyNoDiagnosticCSharpAsync(string originalSource) @@ -345,17 +381,6 @@ private async Task VerifyNoDiagnosticCSharpAsync(string originalSource) await test.RunAsync(); } - private async Task VerifyDiagnosticOnlyCSharpAsync(string originalSource) - { - VerifyCS.Test test = new() - { - TestCode = originalSource, - MarkupOptions = MarkupOptions.UseFirstDescriptor - }; - - await test.RunAsync(); - } - private async Task VerifyFixCSharpAsync(string originalSource, string fixedSource) { VerifyCS.Test test = new() diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.VisualBasic.Tests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.VisualBasic.Tests.cs index e9cc5e6f0b..f3a46276a0 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.VisualBasic.Tests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.VisualBasic.Tests.cs @@ -15,6 +15,7 @@ public class RecommendCaseInsensitiveStringComparison_VisualBasic_Tests : Recomm [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] [MemberData(nameof(VisualBasicDiagnosedAndFixedNamedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_Assign(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -43,7 +44,7 @@ End Class [Theory] [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] - [MemberData(nameof(VisualBasicDiagnosedAndFixedNamedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_Return(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -68,22 +69,19 @@ End Class } [Theory] - [MemberData(nameof(DiagnosedAndFixedWithEqualsToData))] - [MemberData(nameof(DiagnosedAndFixedWithEqualsToInvertedData))] - [MemberData(nameof(VisualBasicDiagnosedAndFixedWithEqualsToNamedData))] - public async Task Diagnostic_If(string diagnosedLine, string fixedLine, string equalsTo) + [MemberData(nameof(DiagnosedAndFixedImplicitBooleanData))] + [MemberData(nameof(DiagnosedAndFixedWithAppendedMethodData))] + [MemberData(nameof(DiagnosedAndFixedWithAppendedMethodInvertedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedWithAppendedMethodNamedData))] + public async Task Diagnostic_If(string diagnosedLine, string fixedLine, string appendedMethod) { - if (equalsTo == " == -1") - { - equalsTo = " = -1"; // VB syntax - } - string originalCode = $@"Imports System Class C Private Function M() As Integer Dim a As String = ""aBc"" Dim b As String = ""bc"" - If [|{diagnosedLine}|]{equalsTo} Then + Dim myBoolean As Boolean = False + If [|{diagnosedLine}|]{appendedMethod} Then Return 5 End If Return 4 @@ -95,7 +93,8 @@ Class C Private Function M() As Integer Dim a As String = ""aBc"" Dim b As String = ""bc"" - If {fixedLine}{equalsTo} Then + Dim myBoolean As Boolean = False + If {fixedLine}{appendedMethod} Then Return 5 End If Return 4 @@ -108,7 +107,7 @@ End Class [Theory] [MemberData(nameof(DiagnosedAndFixedData))] [MemberData(nameof(DiagnosedAndFixedInvertedData))] - [MemberData(nameof(VisualBasicDiagnosedAndFixedNamedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedInvertedNamedData))] public async Task Diagnostic_IgnoreResult(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -136,6 +135,7 @@ End Class [MemberData(nameof(DiagnosedAndFixedStringLiteralsData))] [MemberData(nameof(DiagnosedAndFixedStringLiteralsInvertedData))] [MemberData(nameof(VisualBasicDiagnosedAndFixedStringLiteralsNamedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedStringLiteralsInvertedNamedData))] public async Task Diagnostic_StringLiterals_Return(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -159,6 +159,7 @@ End Class [MemberData(nameof(DiagnosedAndFixedStringReturningMethodsData))] [MemberData(nameof(DiagnosedAndFixedStringReturningMethodsInvertedData))] [MemberData(nameof(VisualBasicDiagnosedAndFixedStringReturningMethodsNamedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedStringReturningMethodsInvertedNamedData))] public async Task Diagnostic_StringReturningMethods_Discard(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -195,6 +196,7 @@ End Class [MemberData(nameof(DiagnosedAndFixedParenthesizedInvertedData))] [MemberData(nameof(VisualBasicDiagnosedAndFixedParenthesizedNamedData))] [MemberData(nameof(VisualBasicDiagnosedAndFixedParenthesizedNamedInvertedData))] + [MemberData(nameof(VisualBasicDiagnosedAndFixedParenthesizedComplexCasesData))] public async Task Diagnostic_Parenthesized_ReturnCastedToString(string diagnosedLine, string fixedLine) { string originalCode = $@"Imports System @@ -203,6 +205,8 @@ Public Function GetString() As String Return ""AbC"" End Function Public Function M() As Object + Dim a As String = ""AbC"" + Dim b As String = ""CdE"" Return ([|{diagnosedLine}|]).ToString() End Function End Class"; @@ -212,6 +216,8 @@ Public Function GetString() As String Return ""AbC"" End Function Public Function M() As Object + Dim a As String = ""AbC"" + Dim b As String = ""CdE"" Return ({fixedLine}).ToString() End Function End Class"; @@ -258,9 +264,9 @@ public async Task Diagnostic_Equality_To_Equals_Trivia() Class C Function M(a As String, b As String) As Boolean ' Trivia1 - Dim result As Boolean = [|a.ToLower() = b.ToLowerInvariant()|] ' Trivia2 + Dim result As Boolean = [|a.ToLowerInvariant() = b.ToLowerInvariant()|] ' Trivia2 ' Trivia3 - If [|a.ToLowerInvariant() <> b.ToLower()|] Then ' Trivia4 + If [|a.ToLower() <> b.ToLower()|] Then ' Trivia4 ' Trivia5 Return [|b <> a.ToLowerInvariant()|] ' Trivia6 ' Trivia7 @@ -274,7 +280,7 @@ End Function Class C Function M(a As String, b As String) As Boolean ' Trivia1 - Dim result As Boolean = a.Equals(b, StringComparison.CurrentCultureIgnoreCase) ' Trivia2 + Dim result As Boolean = a.Equals(b, StringComparison.InvariantCultureIgnoreCase) ' Trivia2 ' Trivia3 If Not a.Equals(b, StringComparison.CurrentCultureIgnoreCase) Then ' Trivia4 ' Trivia5 @@ -309,10 +315,32 @@ End Function await VerifyNoDiagnosticVisualBasicAsync(originalCode); } + [Theory] + [MemberData(nameof(DiagnosticNoFixStartsWithContainsIndexOfData))] + public async Task Diagnostic_NoFix_StartsWithContainsIndexOf(string diagnosedLine) + { + string originalCode = $@"Imports System +Class C + Public Function GetStringA() As String + Return ""aBc"" + End Function + Public Function GetStringB() As String + Return ""cDe"" + End Function + Public Function M() As Object + Dim a As String = ""AbC"" + Dim b As String = ""CdE"" + Return [|{diagnosedLine}|] + End Function +End Class"; + await VerifyFixVisualBasicAsync(originalCode, originalCode); + } + [Theory] [MemberData(nameof(DiagnosticNoFixCompareToData))] [MemberData(nameof(DiagnosticNoFixCompareToInvertedData))] [MemberData(nameof(VisualBasicDiagnosticNoFixCompareToNamedData))] + [MemberData(nameof(VisualBasicDiagnosticNoFixCompareToInvertedNamedData))] public async Task Diagnostic_NoFix_CompareTo(string diagnosedLine) { string originalCode = $@"Imports System @@ -329,7 +357,7 @@ Public Function M() As Integer Return [|{diagnosedLine}|] End Function End Class"; - await VerifyDiagnosticOnlyVisualBasicAsync(originalCode); + await VerifyFixVisualBasicAsync(originalCode, originalCode); } [Theory] @@ -338,12 +366,17 @@ public async Task Diagnostic_NoFix_Equals(string diagnosedLine) { string originalCode = $@"Imports System Class C + Public Function GetString() As String + Return String.Empty + End Function Public Function M() As Boolean + Dim a As String = ""aBc"" + Dim b As String = ""dEf"" Return [|{diagnosedLine}|] End Function End Class"; - await VerifyDiagnosticOnlyVisualBasicAsync(originalCode); + await VerifyFixVisualBasicAsync(originalCode, originalCode); } private async Task VerifyNoDiagnosticVisualBasicAsync(string originalSource) @@ -357,17 +390,6 @@ private async Task VerifyNoDiagnosticVisualBasicAsync(string originalSource) await test.RunAsync(); } - private async Task VerifyDiagnosticOnlyVisualBasicAsync(string originalSource) - { - VerifyVB.Test test = new() - { - TestCode = originalSource, - MarkupOptions = MarkupOptions.UseFirstDescriptor - }; - - await test.RunAsync(); - } - private async Task VerifyFixVisualBasicAsync(string originalSource, string fixedSource) { VerifyVB.Test test = new() diff --git a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Performance/BasicRecommendCaseInsensitiveStringComparisonFixer.vb b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Performance/BasicRecommendCaseInsensitiveStringComparisonFixer.vb index 61f1b6c770..3917d992d8 100644 --- a/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Performance/BasicRecommendCaseInsensitiveStringComparisonFixer.vb +++ b/src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Performance/BasicRecommendCaseInsensitiveStringComparisonFixer.vb @@ -14,86 +14,117 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Performance Public NotInheritable Class BasicRecommendCaseInsensitiveStringComparisonFixer Inherits RecommendCaseInsensitiveStringComparisonFixer - Protected Overrides Function GetNewArgumentsForInvocation(generator As SyntaxGenerator, caseChangingApproachValue As String, - mainInvocationOperation As IInvocationOperation, stringComparisonType As INamedTypeSymbol, - ByRef mainInvocationInstance As SyntaxNode) As IEnumerable(Of SyntaxNode) + Protected Overrides Function GetNewArgumentsForInvocation(generator As SyntaxGenerator, + caseChangingApproachValue As String, mainInvocationOperation As IInvocationOperation, stringComparisonType As INamedTypeSymbol, + leftOffendingMethod As String, rightOffendingMethod As String, ByRef mainInvocationInstance As SyntaxNode) As IEnumerable(Of SyntaxNode) - Dim paramName As String = RecommendCaseInsensitiveStringComparisonAnalyzer.StringParameterName + Dim invocationExpression As InvocationExpressionSyntax = TryCast(mainInvocationOperation.Syntax, InvocationExpressionSyntax) - Dim arguments As New List(Of SyntaxNode) - Dim isAnyArgumentNamed As Boolean = False - - Dim invocationExpression As InvocationExpressionSyntax = DirectCast(mainInvocationOperation.Syntax, InvocationExpressionSyntax) - - Dim isChangingCaseInArgument As Boolean = False mainInvocationInstance = Nothing Dim memberAccessExpression As MemberAccessExpressionSyntax = TryCast(invocationExpression.Expression, MemberAccessExpressionSyntax) - If memberAccessExpression IsNot Nothing Then + Dim internalExpression As ExpressionSyntax = memberAccessExpression.Expression - Dim internalExpression As ExpressionSyntax - - Dim parenthesizedExpression As ParenthesizedExpressionSyntax = TryCast(memberAccessExpression.Expression, ParenthesizedExpressionSyntax) - - internalExpression = If(parenthesizedExpression IsNot Nothing, - parenthesizedExpression.Expression, - memberAccessExpression.Expression) + Dim parenthesizedExpression As ParenthesizedExpressionSyntax = TryCast(internalExpression, ParenthesizedExpressionSyntax) + While parenthesizedExpression IsNot Nothing + internalExpression = parenthesizedExpression.Expression + parenthesizedExpression = TryCast(internalExpression, ParenthesizedExpressionSyntax) + End While Dim internalInvocationExpression As InvocationExpressionSyntax = TryCast(internalExpression, InvocationExpressionSyntax) Dim internalMemberAccessExpression As MemberAccessExpressionSyntax = Nothing - If internalInvocationExpression IsNot Nothing Then internalMemberAccessExpression = TryCast(internalInvocationExpression.Expression, MemberAccessExpressionSyntax) End If - If internalMemberAccessExpression IsNot Nothing Then + If leftOffendingMethod IsNot Nothing AndAlso + internalInvocationExpression IsNot Nothing AndAlso + internalMemberAccessExpression IsNot Nothing AndAlso + internalMemberAccessExpression.Name IsNot Nothing AndAlso + internalMemberAccessExpression.Name.Identifier.Text IsNot Nothing AndAlso + internalMemberAccessExpression.Name.Identifier.Text = leftOffendingMethod Then + mainInvocationInstance = internalMemberAccessExpression.Expression Else mainInvocationInstance = memberAccessExpression.Expression - isChangingCaseInArgument = True End If End If - For Each node As SimpleArgumentSyntax In invocationExpression.ArgumentList.Arguments + Dim arguments As New List(Of SyntaxNode) + Dim isAnyArgumentNamed As Boolean = False - Dim argumentName As String = node.NameColonEquals?.Name.Identifier.ValueText - isAnyArgumentNamed = isAnyArgumentNamed Or argumentName IsNot Nothing + For Each arg As IArgumentOperation In mainInvocationOperation.Arguments - Dim argumentParenthesizedExpression As ParenthesizedExpressionSyntax = TryCast(node.Expression, ParenthesizedExpressionSyntax) + Dim newArgumentNode As SyntaxNode - Dim argumentExpression As ExpressionSyntax = If(argumentParenthesizedExpression IsNot Nothing, - argumentParenthesizedExpression.Expression, - node.Expression) + Dim actualArgumentNode As SyntaxNode = arg.Syntax - Dim argumentMemberAccessExpression As MemberAccessExpressionSyntax = Nothing - Dim argumentInvocationExpression As InvocationExpressionSyntax = TryCast(argumentExpression, InvocationExpressionSyntax) + Dim argumentSyntaxNode As SimpleArgumentSyntax = TryCast(actualArgumentNode, SimpleArgumentSyntax) + While argumentSyntaxNode Is Nothing + actualArgumentNode = actualArgumentNode.Parent + argumentSyntaxNode = TryCast(actualArgumentNode, SimpleArgumentSyntax) + End While - If argumentInvocationExpression IsNot Nothing Then - argumentMemberAccessExpression = TryCast(argumentInvocationExpression.Expression, MemberAccessExpressionSyntax) + If actualArgumentNode IsNot Nothing Then + argumentSyntaxNode = TryCast(actualArgumentNode, SimpleArgumentSyntax) End If - Dim newArgumentNode As SyntaxNode - If isChangingCaseInArgument Then - If argumentMemberAccessExpression IsNot Nothing Then + Dim argumentName As String = Nothing + If argumentSyntaxNode IsNot Nothing AndAlso + argumentSyntaxNode.NameColonEquals IsNot Nothing AndAlso + argumentSyntaxNode.NameColonEquals.Name IsNot Nothing AndAlso + argumentSyntaxNode.NameColonEquals.Name.Identifier.ValueText IsNot Nothing Then + argumentName = argumentSyntaxNode.NameColonEquals.Name.Identifier.ValueText + End If - newArgumentNode = If(argumentName = paramName, - generator.Argument(paramName, RefKind.None, argumentMemberAccessExpression.Expression), - generator.Argument(argumentMemberAccessExpression.Expression)) + isAnyArgumentNamed = isAnyArgumentNamed Or argumentName IsNot Nothing - Else + If rightOffendingMethod IsNot Nothing And arg.Parameter.Type.Name = StringTypeName Then + Dim desiredExpression As ExpressionSyntax = Nothing + + Dim argumentExpression As SimpleArgumentSyntax = TryCast(arg.Syntax, SimpleArgumentSyntax) + Dim argumentInvocationExpression As InvocationExpressionSyntax = TryCast(arg.Syntax, InvocationExpressionSyntax) + + If argumentExpression IsNot Nothing Then - newArgumentNode = node + desiredExpression = argumentExpression.Expression + Dim parenthesizedExpression As ParenthesizedExpressionSyntax = TryCast(desiredExpression, ParenthesizedExpressionSyntax) + While parenthesizedExpression IsNot Nothing + desiredExpression = parenthesizedExpression.Expression + parenthesizedExpression = TryCast(desiredExpression, ParenthesizedExpressionSyntax) + End While + + ElseIf argumentInvocationExpression IsNot Nothing Then + + desiredExpression = argumentInvocationExpression End If - Else - newArgumentNode = node + Dim invocation As InvocationExpressionSyntax = TryCast(desiredExpression, InvocationExpressionSyntax) + Dim argumentMemberAccessExpression As MemberAccessExpressionSyntax = Nothing + If invocation IsNot Nothing Then + argumentMemberAccessExpression = TryCast(invocation.Expression, MemberAccessExpressionSyntax) + End If + + If invocation IsNot Nothing And argumentMemberAccessExpression IsNot Nothing Then + + If argumentName = RecommendCaseInsensitiveStringComparisonAnalyzer.StringParameterName Then + newArgumentNode = generator.Argument(RecommendCaseInsensitiveStringComparisonAnalyzer.StringParameterName, RefKind.None, argumentMemberAccessExpression.Expression) + Else + newArgumentNode = generator.Argument(argumentMemberAccessExpression.Expression) + End If + + Else + newArgumentNode = arg.Syntax + End If + Else + newArgumentNode = arg.Syntax End If - arguments.Add(newArgumentNode.WithTriviaFrom(node)) + arguments.Add(newArgumentNode.WithTriviaFrom(arg.Syntax)) Next