Skip to content

Commit

Permalink
New rule IDE0159 - Use 'Order' instead of 'OrderBy'
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Jun 13, 2024
1 parent 309de01 commit 16c3af1
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ If you are already using other analyzers, you can check [which rules are duplica
|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\<T\>|⚠️|||
|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method does not return IAsyncEnumerable\<T\>|⚠️|||
|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|⚠️|✔️||
|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|ℹ️|✔️|✔️|

<!-- rules -->

Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\<T\>|<span title='Warning'>⚠️</span>|||
|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method does not return IAsyncEnumerable\<T\>|<span title='Warning'>⚠️</span>|||
|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|<span title='Warning'>⚠️</span>|✔️||
|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|<span title='Info'>ℹ️</span>|✔️|✔️|

|Id|Suppressed rule|Justification|
|--|---------------|-------------|
Expand Down Expand Up @@ -638,6 +639,9 @@ dotnet_diagnostic.MA0157.severity = none
# MA0158: Use System.Threading.Lock
dotnet_diagnostic.MA0158.severity = warning
# MA0159: Use 'Order' instead of 'OrderBy'
dotnet_diagnostic.MA0159.severity = suggestion
```

# .editorconfig - all rules disabled
Expand Down Expand Up @@ -1113,4 +1117,7 @@ dotnet_diagnostic.MA0157.severity = none
# MA0158: Use System.Threading.Lock
dotnet_diagnostic.MA0158.severity = none
# MA0159: Use 'Order' instead of 'OrderBy'
dotnet_diagnostic.MA0159.severity = none
```
13 changes: 13 additions & 0 deletions docs/Rules/MA0159.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# MA0159 - Use 'Order' instead of 'OrderBy'

Use `Order` instead of `OrderBy(x => x)` to order a collection.

````c#
IEnumerable<int> numbers = [1, 2];
var orderedNumbers = numbers.OrderBy(n => n); // non-compliant
````

````c#
IEnumerable<int> numbers = [1, 2];
var orderedNumbers = numbers.Order(); // compliant
````
28 changes: 26 additions & 2 deletions src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public sealed class OptimizeLinqUsageFixer : CodeFixProvider
RuleIdentifiers.DuplicateEnumerable_OrderBy,
RuleIdentifiers.OptimizeEnumerable_CombineMethods,
RuleIdentifiers.OptimizeEnumerable_Count,
RuleIdentifiers.OptimizeEnumerable_CastInsteadOfSelect);
RuleIdentifiers.OptimizeEnumerable_CastInsteadOfSelect,
RuleIdentifiers.OptimizeEnumerable_UseOrder);

public override FixAllProvider GetFixAllProvider()
{
Expand All @@ -45,7 +46,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (diagnostic is null)
return;

if (!Enum.TryParse(diagnostic.Properties.GetValueOrDefault("Data", ""), ignoreCase: false, out OptimizeLinqUsageData data) || data == OptimizeLinqUsageData.None)
if (!Enum.TryParse(diagnostic.Properties.GetValueOrDefault("Data", ""), ignoreCase: false, out OptimizeLinqUsageData data) || data is OptimizeLinqUsageData.None)
return;

// If the so-called nodeToFix is a Name (most likely a method name such as 'Select' or 'Count'),
Expand Down Expand Up @@ -146,6 +147,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
case OptimizeLinqUsageData.UseCastInsteadOfSelect:
context.RegisterCodeFix(CodeAction.Create(title, ct => UseCastInsteadOfSelect(context.Document, nodeToFix, ct), equivalenceKey: title), context.Diagnostics);
break;

case OptimizeLinqUsageData.UseOrder:
context.RegisterCodeFix(CodeAction.Create(title, ct => UseOrderInsteadOfOrderBy(context.Document, nodeToFix, ct), equivalenceKey: title), context.Diagnostics);
break;
}
}

Expand Down Expand Up @@ -363,6 +368,25 @@ private static async Task<Document> UseConstantValue(Document document, SyntaxNo
return editor.GetChangedDocument();
}

private static async Task<Document> UseOrderInsteadOfOrderBy(Document document, SyntaxNode nodeToFix, CancellationToken cancellationToken)
{
if (nodeToFix is not InvocationExpressionSyntax invocation)
return document;

var member = GetMemberAccessExpression(nodeToFix);
if (member is null)
return document;

var newName = member.Name.Identifier.ValueText is "OrderBy" ? "Order" : "OrderDescending";

var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var generator = editor.Generator;

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, default)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, default)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.6)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.6)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.2)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.2)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn3.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn3.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.4)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (ubuntu-latest, Release, roslyn4.4)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.4)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.4)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.6)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.6)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, default)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, default)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.2)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn4.2)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / create_nuget

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / create_nuget

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / create_nuget

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / create_nuget

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn3.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

Check failure on line 383 in src/Meziantou.Analyzer.CodeFixers/Rules/OptimizeLinqUsageFixer.cs

View workflow job for this annotation

GitHub Actions / build_and_test (windows-latest, Release, roslyn3.8)

Unnecessary assignment of a value to 'generator' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059)

editor.RemoveNode(invocation.ArgumentList.Arguments.First());
editor.ReplaceNode(member, member.WithName(IdentifierName(newName)));
return editor.GetChangedDocument();
}

private static async Task<Document> UseLengthProperty(Document document, SyntaxNode nodeToFix, CancellationToken cancellationToken)
{
var expression = GetParentMemberExpression(nodeToFix);
Expand Down
1 change: 1 addition & 0 deletions src/Meziantou.Analyzer/RuleIdentifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ internal static class RuleIdentifiers
public const string MethodsReturningIAsyncEnumerableMustHaveTheAsyncSuffix = "MA0156";
public const string MethodsNotReturningIAsyncEnumerableMustNotHaveTheAsyncSuffix = "MA0157";
public const string UseSystemThreadingLockInsteadOfObject = "MA0158";
public const string OptimizeEnumerable_UseOrder = "MA0159";

public static string GetHelpUri(string identifier)
{
Expand Down
41 changes: 38 additions & 3 deletions src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ public sealed class OptimizeLinqUsageAnalyzer : DiagnosticAnalyzer
description: "",
helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.OptimizeEnumerable_UseCountInsteadOfAny));

private static readonly DiagnosticDescriptor UseOrderRule = new(
RuleIdentifiers.OptimizeEnumerable_UseOrder,
title: "Use 'Order' instead of 'OrderBy'",
messageFormat: "Use '{0}' instead of '{0}By'",
RuleCategories.Performance,
DiagnosticSeverity.Info,
isEnabledByDefault: true,
description: "",
helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.OptimizeEnumerable_UseOrder));

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
ListMethodsRule,
IndexerInsteadOfElementAtRule,
Expand All @@ -104,7 +114,8 @@ public sealed class OptimizeLinqUsageAnalyzer : DiagnosticAnalyzer
OptimizeCountRule,
OptimizeWhereAndOrderByRule,
UseCastInsteadOfSelect,
UseCountInsteadOfAny);
UseCountInsteadOfAny,
UseOrderRule);

public override void Initialize(AnalysisContext context)
{
Expand Down Expand Up @@ -137,6 +148,8 @@ public AnalyzerContext(Compilation compilation)
IListOfTSymbol = compilation.GetBestTypeByMetadataName("System.Collections.Generic.IList`1");
IReadOnlyListOfTSymbol = compilation.GetBestTypeByMetadataName("System.Collections.Generic.IReadOnlyList`1");
ICollectionSymbol = compilation.GetBestTypeByMetadataName("System.Collections.ICollection");

HasEnumerableOrderMethod = DocumentationCommentId.GetFirstSymbolForDeclarationId("M:System.Linq.Enumerable.Order``1(System.Collections.Generic.IEnumerable{``0})", compilation) is not null;
}

public bool IsValid => ExtensionMethodOwnerTypes.Count > 0;
Expand All @@ -152,6 +165,7 @@ public AnalyzerContext(Compilation compilation)
private INamedTypeSymbol? IListOfTSymbol { get; set; }
private INamedTypeSymbol? IReadOnlyListOfTSymbol { get; set; }
private INamedTypeSymbol? ICollectionSymbol { get; set; }
private bool HasEnumerableOrderMethod { get; set; }

public void AnalyzeInvocation(OperationAnalysisContext context)
{
Expand All @@ -170,6 +184,7 @@ public void AnalyzeInvocation(OperationAnalysisContext context)
UseIndexerInsteadOfElementAt(context, operation);
CombineWhereWithNextMethod(context, operation);
RemoveTwoConsecutiveOrderBy(context, operation);
UseOrder(context, operation);
WhereShouldBeBeforeOrderBy(context, operation);
OptimizeCountUsage(context, operation);
UseCastInsteadOfSelect(context, operation);
Expand All @@ -183,8 +198,7 @@ public void AnalyzeInvocation(OperationAnalysisContext context)

private void WhereShouldBeBeforeOrderBy(OperationAnalysisContext context, IInvocationOperation operation)
{
if (operation.TargetMethod.Name == nameof(Enumerable.OrderBy) ||
operation.TargetMethod.Name == nameof(Enumerable.OrderByDescending))
if (operation.TargetMethod.Name is (nameof(Enumerable.OrderBy)) or (nameof(Enumerable.OrderByDescending)))
{
var parent = GetParentLinqOperation(operation);
if (parent is not null && ExtensionMethodOwnerTypes.Contains(parent.TargetMethod.ContainingType))
Expand Down Expand Up @@ -484,6 +498,27 @@ private void RemoveTwoConsecutiveOrderBy(OperationAnalysisContext context, IInvo
}
}

private void UseOrder(OperationAnalysisContext context, IInvocationOperation operation)
{
if (!HasEnumerableOrderMethod)
return;

if (operation.TargetMethod.Name is nameof(Enumerable.OrderBy) or nameof(Enumerable.OrderByDescending) && operation.TargetMethod.ContainingType.IsEqualTo(EnumerableSymbol) && operation.Arguments.Length > 0)
{
var arg = operation.Arguments[1].Value;

// x => x
if (arg is IDelegateCreationOperation { Target: IAnonymousFunctionOperation { Symbol.Parameters: [var delegateParameter], Body: IBlockOperation { Operations: [IReturnOperation { ReturnedValue: IParameterReferenceOperation parameterReference }] } } } && parameterReference.Parameter.IsEqualTo(delegateParameter))
{
var properties = CreateProperties(OptimizeLinqUsageData.UseOrder)
.Add("FirstOperationStart", operation.Syntax.Span.Start.ToString(CultureInfo.InvariantCulture))
.Add("FirstOperationLength", operation.Syntax.Span.Length.ToString(CultureInfo.InvariantCulture));

context.ReportDiagnostic(UseOrderRule, properties, operation, DiagnosticInvocationReportOptions.ReportOnMember, operation.TargetMethod.Name);
}
}
}

private void OptimizeCountUsage(OperationAnalysisContext context, IInvocationOperation operation)
{
if (operation.TargetMethod.Name != nameof(Enumerable.Count))
Expand Down
1 change: 1 addition & 0 deletions src/Meziantou.Analyzer/Rules/OptimizeLinqUsageData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ internal enum OptimizeLinqUsageData
UseTrueForAllMethodWithConversion,
UseExistsMethod,
UseExistsMethodWithConversion,
UseOrder,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using System.Threading.Tasks;
using Meziantou.Analyzer.Rules;
using TestHelper;
using Xunit;

namespace Meziantou.Analyzer.Test.Rules;

public sealed class OptimizeLinqUsageAnalyzerOrderTests
{
private static ProjectBuilder CreateProjectBuilder()
{
return new ProjectBuilder()
.WithTargetFramework(TargetFramework.Net8_0)
.WithAnalyzer<OptimizeLinqUsageAnalyzer>(id: RuleIdentifiers.OptimizeEnumerable_UseOrder)
.WithCodeFixProvider<OptimizeLinqUsageFixer>();
}

[Fact]
public async Task IEnumerable_Order_net5()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net5_0)
.WithSourceCode("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.OrderBy(x => x);
}
}
""")
.ValidateAsync();
}

[Fact]
public async Task IEnumerable_Order_LambdaNotValid()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net5_0)
.WithSourceCode("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.OrderBy(x => true);
}
}
""")
.ValidateAsync();
}

[Fact]
public async Task IEnumerable_Order_LambdaReferenceAnotherParameter()
{
await CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net5_0)
.WithSourceCode("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test(int a)
{
IEnumerable<string> query = null;
query.OrderBy(x => a);
}
}
""")
.ValidateAsync();
}

[Fact]
public async Task IEnumerable_Order()
{
await CreateProjectBuilder()
.WithSourceCode("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.[|OrderBy|](x => x);
}
}
""")
.ShouldFixCodeWith("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.Order();
}
}
""")
.ValidateAsync();
}

[Fact]
public async Task IEnumerable_OrderDescending()
{
await CreateProjectBuilder()
.WithSourceCode("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.[|OrderByDescending|](x => x);
}
}
""")
.ShouldFixCodeWith("""
using System.Collections.Generic;
using System.Linq;
class Test
{
public Test()
{
IEnumerable<string> query = null;
query.OrderDescending();
}
}
""")
.ValidateAsync();
}
}

0 comments on commit 16c3af1

Please sign in to comment.