From 9987127feb881550195c36538d6d4eefac94430e Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 15 Oct 2022 00:45:11 +0200 Subject: [PATCH 1/5] Order arguments properly --- .../BaseArgumentListCodeFixProvider.cs | 4 +- .../Analysis/OrderNamedArgumentsAnalyzer.cs | 135 +++++++++++++----- .../RCS1205OrderNamedArgumentsTests.cs | 56 ++++++++ 3 files changed, 158 insertions(+), 37 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs index 7ab53ecf29..a42a3295de 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs @@ -61,11 +61,11 @@ private static async Task OrderNamedArgumentsAsync( SeparatedSyntaxList arguments = argumentList.Arguments; - int firstIndex = OrderNamedArgumentsAnalyzer.IndexOfFirstFixableParameter(argumentList, arguments, semanticModel, cancellationToken); + (int first, int last) = OrderNamedArgumentsAnalyzer.FindFixableSpan(argumentList, arguments, semanticModel, cancellationToken).Value; SeparatedSyntaxList newArguments = arguments; - for (int i = firstIndex; i < arguments.Count; i++) + for (int i = first; i <= last; i++) { IParameterSymbol parameter = parameters[i]; diff --git a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs index 85e2d20e5f..2b40b289d2 100644 --- a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs @@ -1,8 +1,10 @@ // Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -45,12 +47,12 @@ private static void AnalyzeBaseArgumentList(SyntaxNodeAnalysisContext context) SeparatedSyntaxList arguments = argumentList.Arguments; - int index = IndexOfFirstFixableParameter(argumentList, arguments, context.SemanticModel, context.CancellationToken); + (int first, int last)? range = FindFixableSpan(argumentList, arguments, context.SemanticModel, context.CancellationToken); - if (index == -1) + if (range is null) return; - TextSpan span = TextSpan.FromBounds(arguments[index].SpanStart, arguments.Last().Span.End); + TextSpan span = TextSpan.FromBounds(arguments[range.Value.first].SpanStart, arguments[range.Value.last].Span.End); if (argumentList.ContainsDirectives(span)) return; @@ -58,10 +60,10 @@ private static void AnalyzeBaseArgumentList(SyntaxNodeAnalysisContext context) DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.OrderNamedArguments, - Location.Create(argumentList.SyntaxTree, span)); + Location.Create(context.Node.SyntaxTree, span)); } - public static int IndexOfFirstFixableParameter( + internal static (int first, int last)? FindFixableSpan( BaseArgumentListSyntax argumentList, SeparatedSyntaxList arguments, SemanticModel semanticModel, @@ -69,63 +71,126 @@ public static int IndexOfFirstFixableParameter( { int firstIndex = -1; - for (int i = 0; i < arguments.Count; i++) + for (int i = arguments.Count - 1; i >= 0; i--) { if (arguments[i].NameColon != null) { firstIndex = i; + } + else + { break; } } - if (firstIndex != -1 - && firstIndex != arguments.Count - 1) + if (firstIndex < 0) + return null; + + if (firstIndex >= arguments.Count - 1) + return null; + + ISymbol symbol = semanticModel.GetSymbol(argumentList.Parent, cancellationToken); + + if (symbol is null) + return null; + + ImmutableArray parameters = symbol.ParametersOrDefault(); + + Debug.Assert(!parameters.IsDefault, symbol.Kind.ToString()); + + if (parameters.IsDefault) + return null; + + if (parameters.Length < arguments.Count) + return null; + + if (!IsFixable(firstIndex, arguments, parameters)) + return null; + + var items = new List<(ArgumentSyntax, int)>(); + + for (int i = firstIndex; i < arguments.Count; i++) { - ISymbol symbol = semanticModel.GetSymbol(argumentList.Parent, cancellationToken); + IParameterSymbol parameter = parameters.FirstOrDefault(g => g.Name == arguments[i].NameColon.Name.Identifier.ValueText); - if (symbol != null) + if (parameter is null) { - ImmutableArray parameters = symbol.ParametersOrDefault(); + return null; + } + + items.Add((arguments[i], parameters.IndexOf(parameter))); + } - Debug.Assert(!parameters.IsDefault, symbol.Kind.ToString()); + items.Sort((x, y) => x.Item2.CompareTo(y.Item2)); - if (!parameters.IsDefault - && parameters.Length >= arguments.Count) + int first = firstIndex; + int last = arguments.Count - 1; + + while (first < arguments.Count) + { + if (items[first - firstIndex].Item1 == arguments[first]) + { + first++; + } + else + { + while (last > first) { - for (int i = firstIndex; i < arguments.Count; i++) + if (items[last - firstIndex].Item1 == arguments[last]) + { + last--; + } + else { - ArgumentSyntax argument = arguments[i]; + return (first, last); + } + } + } + } - NameColonSyntax nameColon = argument.NameColon; + return null; + } - if (nameColon == null) - break; + private static bool IsFixable(int firstIndex, SeparatedSyntaxList arguments, ImmutableArray parameters) + { + int j = -1; + string name = arguments[firstIndex].NameColon.Name.Identifier.ValueText; - if (!string.Equals( - nameColon.Name.Identifier.ValueText, - parameters[i].Name, - StringComparison.Ordinal)) - { - int fixableIndex = i; + for (int i = 0; i < parameters.Length; i++) + { + if (parameters[i].Name == name) + { + j = i; + break; + } + } - i++; + if (j == -1) + return false; - while (i < arguments.Count) - { - if (arguments[i].NameColon == null) - break; + for (int i = firstIndex + 1; i < arguments.Count; i++) + { + name = arguments[i].NameColon.Name.Identifier.ValueText; - i++; - } + while (!string.Equals( + name, + parameters[j].Name, + StringComparison.Ordinal)) + { + j++; - return fixableIndex; - } + if (j == parameters.Length) + { + foreach (IParameterSymbol parameter in parameters) + { + if (parameter.Name == name) + return true; } } } } - return -1; + return false; } } } diff --git a/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs b/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs index 48116826ed..0eb68865c1 100644 --- a/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs @@ -53,6 +53,62 @@ void M(string a, string b, string c, string d = null) M(a: ""a"", b: ""b"", c: ""c""); } } +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OrderNamedArguments)] + public async Task Test_OptionalArguments2() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M(string a, string b = """", string c = """", string d = """", string e = """") + { + M( + """", + b: """", + """", + [|e: """", + d: """"|]); + } +} +", @" +class C +{ + void M(string a, string b = """", string c = """", string d = """", string e = """") + { + M( + """", + b: """", + """", + d: """", + e: """"); + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OrderNamedArguments)] + public async Task TestNoDiagnostic_OptionalArguments() + { + await VerifyNoDiagnosticAsync(@" +class C +{ + void M(string a, string b = """", string c = """", string d = """") + { + M( + """", + b: """", + d: """"); + } +} +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OrderNamedArguments)] + public async Task TestNoDiagnostic_OptionalArguments2() + { + await VerifyNoDiagnosticAsync(@" "); } } From ea3837a8b53882de6e4340caa76ace36e857f917 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 15 Oct 2022 12:05:19 +0200 Subject: [PATCH 2/5] Update --- .../BaseArgumentListCodeFixProvider.cs | 33 ++-- .../Analysis/OrderNamedArgumentsAnalyzer.cs | 169 +++++++++--------- 2 files changed, 104 insertions(+), 98 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs index a42a3295de..74d73524e8 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs @@ -30,21 +30,24 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) if (!TryFindFirstAncestorOrSelf(root, context.Span, out BaseArgumentListSyntax baseArgumentList)) return; - foreach (Diagnostic diagnostic in context.Diagnostics) + if (baseArgumentList.ContainsDirectives(context.Span)) + return; + + Document document = context.Document; + Diagnostic diagnostic = context.Diagnostics[0]; + + switch (diagnostic.Id) { - switch (diagnostic.Id) - { - case DiagnosticIdentifiers.OrderNamedArguments: - { - CodeAction codeAction = CodeAction.Create( - "Order arguments", - ct => OrderNamedArgumentsAsync(context.Document, baseArgumentList, ct), - GetEquivalenceKey(diagnostic)); - - context.RegisterCodeFix(codeAction, diagnostic); - break; - } - } + case DiagnosticIdentifiers.OrderNamedArguments: + { + CodeAction codeAction = CodeAction.Create( + "Order arguments", + ct => OrderNamedArgumentsAsync(document, baseArgumentList, ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + break; + } } } @@ -61,7 +64,7 @@ private static async Task OrderNamedArgumentsAsync( SeparatedSyntaxList arguments = argumentList.Arguments; - (int first, int last) = OrderNamedArgumentsAnalyzer.FindFixableSpan(argumentList, arguments, semanticModel, cancellationToken).Value; + (int first, int last) = OrderNamedArgumentsAnalyzer.FindFixableSpan(arguments, semanticModel, cancellationToken); SeparatedSyntaxList newArguments = arguments; diff --git a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs index 2b40b289d2..ec6bcf8c6f 100644 --- a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs @@ -43,28 +43,26 @@ private static void AnalyzeBaseArgumentList(SyntaxNodeAnalysisContext context) if (context.Node.ContainsDiagnostics) return; - var argumentList = (BaseArgumentListSyntax)context.Node; + SeparatedSyntaxList arguments = ((BaseArgumentListSyntax)context.Node).Arguments; - SeparatedSyntaxList arguments = argumentList.Arguments; - - (int first, int last)? range = FindFixableSpan(argumentList, arguments, context.SemanticModel, context.CancellationToken); - - if (range is null) - return; - - TextSpan span = TextSpan.FromBounds(arguments[range.Value.first].SpanStart, arguments[range.Value.last].Span.End); - - if (argumentList.ContainsDirectives(span)) - return; + if (arguments.Count >= 2) + { + (int first, int last) = FindFixableSpan(arguments, context.SemanticModel, context.CancellationToken); - DiagnosticHelpers.ReportDiagnostic( - context, - DiagnosticRules.OrderNamedArguments, - Location.Create(context.Node.SyntaxTree, span)); + if (first >= 0 + && last > 0) + { + DiagnosticHelpers.ReportDiagnostic( + context, + DiagnosticRules.OrderNamedArguments, + Location.Create( + context.Node.SyntaxTree, + TextSpan.FromBounds(arguments[first].SpanStart, arguments[last].Span.End))); + } + } } - internal static (int first, int last)? FindFixableSpan( - BaseArgumentListSyntax argumentList, + internal static (int first, int last) FindFixableSpan( SeparatedSyntaxList arguments, SemanticModel semanticModel, CancellationToken cancellationToken) @@ -83,52 +81,99 @@ internal static (int first, int last)? FindFixableSpan( } } - if (firstIndex < 0) - return null; + if (firstIndex >= 0 + && firstIndex < arguments.Count - 1) + { + ISymbol symbol = semanticModel.GetSymbol(arguments.First().Parent.Parent, cancellationToken); - if (firstIndex >= arguments.Count - 1) - return null; + if (symbol is not null) + { + ImmutableArray parameters = symbol.ParametersOrDefault(); - ISymbol symbol = semanticModel.GetSymbol(argumentList.Parent, cancellationToken); + Debug.Assert(!parameters.IsDefault, symbol.Kind.ToString()); - if (symbol is null) - return null; + if (!parameters.IsDefault + && parameters.Length >= arguments.Count + && IsFixable(firstIndex, arguments, parameters)) + { + return GetFixableSpan(firstIndex, arguments, parameters); + } + } + } - ImmutableArray parameters = symbol.ParametersOrDefault(); + return default; + } - Debug.Assert(!parameters.IsDefault, symbol.Kind.ToString()); + private static bool IsFixable( + int firstIndex, + SeparatedSyntaxList arguments, + ImmutableArray parameters) + { + int j = -1; + string firstName = arguments[firstIndex].NameColon.Name.Identifier.ValueText; - if (parameters.IsDefault) - return null; + for (int i = 0; i < parameters.Length; i++) + { + if (parameters[i].Name == firstName) + { + j = i; + break; + } + } - if (parameters.Length < arguments.Count) - return null; + if (j >= 0) + { + for (int i = firstIndex + 1; i < arguments.Count; i++) + { + string name = arguments[i].NameColon.Name.Identifier.ValueText; - if (!IsFixable(firstIndex, arguments, parameters)) - return null; + while (!string.Equals( + name, + parameters[j].Name, + StringComparison.Ordinal)) + { + j++; - var items = new List<(ArgumentSyntax, int)>(); + if (j == parameters.Length) + { + foreach (IParameterSymbol parameter in parameters) + { + if (parameter.Name == name) + return true; + } + } + } + } + } + + return false; + } + + private static (int first, int last) GetFixableSpan( + int firstIndex, + SeparatedSyntaxList arguments, + ImmutableArray parameters) + { + var items = new List<(ArgumentSyntax argument, int ordinal)>(); for (int i = firstIndex; i < arguments.Count; i++) { IParameterSymbol parameter = parameters.FirstOrDefault(g => g.Name == arguments[i].NameColon.Name.Identifier.ValueText); if (parameter is null) - { - return null; - } + return default; items.Add((arguments[i], parameters.IndexOf(parameter))); } - items.Sort((x, y) => x.Item2.CompareTo(y.Item2)); + items.Sort((x, y) => x.ordinal.CompareTo(y.ordinal)); int first = firstIndex; int last = arguments.Count - 1; while (first < arguments.Count) { - if (items[first - firstIndex].Item1 == arguments[first]) + if (items[first - firstIndex].argument == arguments[first]) { first++; } @@ -136,7 +181,7 @@ internal static (int first, int last)? FindFixableSpan( { while (last > first) { - if (items[last - firstIndex].Item1 == arguments[last]) + if (items[last - firstIndex].argument == arguments[last]) { last--; } @@ -148,49 +193,7 @@ internal static (int first, int last)? FindFixableSpan( } } - return null; - } - - private static bool IsFixable(int firstIndex, SeparatedSyntaxList arguments, ImmutableArray parameters) - { - int j = -1; - string name = arguments[firstIndex].NameColon.Name.Identifier.ValueText; - - for (int i = 0; i < parameters.Length; i++) - { - if (parameters[i].Name == name) - { - j = i; - break; - } - } - - if (j == -1) - return false; - - for (int i = firstIndex + 1; i < arguments.Count; i++) - { - name = arguments[i].NameColon.Name.Identifier.ValueText; - - while (!string.Equals( - name, - parameters[j].Name, - StringComparison.Ordinal)) - { - j++; - - if (j == parameters.Length) - { - foreach (IParameterSymbol parameter in parameters) - { - if (parameter.Name == name) - return true; - } - } - } - } - - return false; + return default; } } } From fa355ee7ff1c2867af4c52d6cd4b1258a71b5a41 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sat, 15 Oct 2022 14:56:03 +0200 Subject: [PATCH 3/5] update --- .../BaseArgumentListCodeFixProvider.cs | 27 ++++++++++-------- .../RCS1205OrderNamedArgumentsTests.cs | 28 +++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs index 74d73524e8..df4ae94fc3 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs @@ -1,8 +1,9 @@ // Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; -using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -66,21 +67,23 @@ private static async Task OrderNamedArgumentsAsync( (int first, int last) = OrderNamedArgumentsAnalyzer.FindFixableSpan(arguments, semanticModel, cancellationToken); + List<(ArgumentSyntax argument, int ordinal)> sortedArguments = arguments + .Skip(first) + .Take(last - first + 1) + .Select(argument => + { + IParameterSymbol parameter = parameters.FirstOrDefault(g => g.Name == argument.NameColon.Name.Identifier.ValueText); + + return (argument, ordinal: parameters.IndexOf(parameter)); + }) + .OrderBy(f => f.ordinal) + .ToList(); + SeparatedSyntaxList newArguments = arguments; for (int i = first; i <= last; i++) { - IParameterSymbol parameter = parameters[i]; - - int index = arguments.IndexOf(f => f.NameColon?.Name.Identifier.ValueText == parameter.Name); - - Debug.Assert(index != -1, parameter.Name); - - if (index != -1 - && index != i) - { - newArguments = newArguments.ReplaceAt(i, arguments[index]); - } + newArguments = newArguments.ReplaceAt(i, sortedArguments[i - first].argument); } BaseArgumentListSyntax newNode = argumentList diff --git a/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs b/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs index 0eb68865c1..205b616e52 100644 --- a/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1205OrderNamedArgumentsTests.cs @@ -88,6 +88,34 @@ void M(string a, string b = """", string c = """", string d = """", string e = " "); } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OrderNamedArguments)] + public async Task Test_OptionalArguments3() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M(string a = """", string b = """", string c = """", string d = """") + { + M( + [|c: """", + b: """"|], + d: """"); + } +} +", @" +class C +{ + void M(string a = """", string b = """", string c = """", string d = """") + { + M( + b: """", + c: """", + d: """"); + } +} +"); + } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OrderNamedArguments)] public async Task TestNoDiagnostic_OptionalArguments() { From 050f39857795e61e0e09f6de5baac6d7d169c66d Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 16 Oct 2022 12:10:51 +0200 Subject: [PATCH 4/5] update --- .../CodeFixes/BaseArgumentListCodeFixProvider.cs | 13 +++++++------ .../CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs | 14 +++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs index df4ae94fc3..7375315080 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/BaseArgumentListCodeFixProvider.cs @@ -67,23 +67,24 @@ private static async Task OrderNamedArgumentsAsync( (int first, int last) = OrderNamedArgumentsAnalyzer.FindFixableSpan(arguments, semanticModel, cancellationToken); - List<(ArgumentSyntax argument, int ordinal)> sortedArguments = arguments + List sortedArguments = arguments .Skip(first) .Take(last - first + 1) - .Select(argument => + .Select(a => { - IParameterSymbol parameter = parameters.FirstOrDefault(g => g.Name == argument.NameColon.Name.Identifier.ValueText); + IParameterSymbol parameter = parameters.First(p => p.Name == a.NameColon.Name.Identifier.ValueText); - return (argument, ordinal: parameters.IndexOf(parameter)); + return (argument: a, ordinal: parameters.IndexOf(parameter)); }) - .OrderBy(f => f.ordinal) + .OrderBy(a => a.ordinal) + .Select(a => a.argument) .ToList(); SeparatedSyntaxList newArguments = arguments; for (int i = first; i <= last; i++) { - newArguments = newArguments.ReplaceAt(i, sortedArguments[i - first].argument); + newArguments = newArguments.ReplaceAt(i, sortedArguments[i - first]); } BaseArgumentListSyntax newNode = argumentList diff --git a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs index ec6bcf8c6f..315a537673 100644 --- a/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/OrderNamedArgumentsAnalyzer.cs @@ -50,7 +50,7 @@ private static void AnalyzeBaseArgumentList(SyntaxNodeAnalysisContext context) (int first, int last) = FindFixableSpan(arguments, context.SemanticModel, context.CancellationToken); if (first >= 0 - && last > 0) + && last > first) { DiagnosticHelpers.ReportDiagnostic( context, @@ -154,26 +154,26 @@ private static (int first, int last) GetFixableSpan( SeparatedSyntaxList arguments, ImmutableArray parameters) { - var items = new List<(ArgumentSyntax argument, int ordinal)>(); + var sortedArgs = new List<(ArgumentSyntax argument, int ordinal)>(); for (int i = firstIndex; i < arguments.Count; i++) { - IParameterSymbol parameter = parameters.FirstOrDefault(g => g.Name == arguments[i].NameColon.Name.Identifier.ValueText); + IParameterSymbol parameter = parameters.FirstOrDefault(p => p.Name == arguments[i].NameColon.Name.Identifier.ValueText); if (parameter is null) return default; - items.Add((arguments[i], parameters.IndexOf(parameter))); + sortedArgs.Add((arguments[i], parameters.IndexOf(parameter))); } - items.Sort((x, y) => x.ordinal.CompareTo(y.ordinal)); + sortedArgs.Sort((x, y) => x.ordinal.CompareTo(y.ordinal)); int first = firstIndex; int last = arguments.Count - 1; while (first < arguments.Count) { - if (items[first - firstIndex].argument == arguments[first]) + if (sortedArgs[first - firstIndex].argument == arguments[first]) { first++; } @@ -181,7 +181,7 @@ private static (int first, int last) GetFixableSpan( { while (last > first) { - if (items[last - firstIndex].argument == arguments[last]) + if (sortedArgs[last - firstIndex].argument == arguments[last]) { last--; } From 2b0bf72c8977c9ac9d40b6d75f1fc7b1254b9f31 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Sun, 16 Oct 2022 12:14:35 +0200 Subject: [PATCH 5/5] update changelog --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index bb697c7e16..8ae12bc703 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add parentheses if necessary in a code fix for [RCS1197](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1197.md) ([#928](https://github.com/josefpihrt/roslynator/pull/928) by @karl-sjogren). - Do not simplify default expression if it would change semantics ([RCS1244](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1244.md)) ([#939](https://github.com/josefpihrt/roslynator/pull/939). - Fix NullReferenceException in [RCS1198](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1198.md) ([#940](https://github.com/josefpihrt/roslynator/pull/940). -- Order named arguments even if optional arguments are not specified [RCS1205](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1205.md) ([#941](https://github.com/josefpihrt/roslynator/pull/941). +- Order named arguments even if optional arguments are not specified [RCS1205](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1205.md) ([#941](https://github.com/josefpihrt/roslynator/pull/941), ([#965](https://github.com/josefpihrt/roslynator/pull/965). - Prefix identifier with `@` if necessary ([RCS1220](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1220.md)) ([#943](https://github.com/josefpihrt/roslynator/pull/943). - Do not suggest to make local variable a const when it is used in ref extension method ([RCS1118](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1118.md)) ([#948](https://github.com/josefpihrt/roslynator/pull/948). - Fix formatting of argument list ([#952](https://github.com/josefpihrt/roslynator/pull/952).