Skip to content

Commit

Permalink
Implement FixAllProvider for RCS1014 (#1070)
Browse files Browse the repository at this point in the history
Co-authored-by: Josef Pihrt <josef@pihrt.net>
  • Loading branch information
jamesHargreaves12 and josefpihrt committed Aug 16, 2023
1 parent 25288a7 commit 47b002c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 24 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add SECURITY.md ([#1147](https://github.com/josefpihrt/roslynator/pull/1147))
- Add custom FixAllProvider for [RCS1014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1014.md) ([#1070](https://github.com/JosefPihrt/Roslynator/pull/1070)).

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +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;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
Expand All @@ -23,6 +25,21 @@ public override ImmutableArray<string> FixableDiagnosticIds
get { return ImmutableArray.Create(DiagnosticIdentifiers.UseExplicitlyOrImplicitlyTypedArray); }
}

public override FixAllProvider GetFixAllProvider()
{
return FixAllProvider.Create(async (context, document, diagnostics) => await FixAllAsync(document, diagnostics, context.CancellationToken).ConfigureAwait(false));
}

private static async Task<Document> FixAllAsync(Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
foreach (Diagnostic diagnostic in diagnostics.OrderByDescending(d => d.Location.SourceSpan.Start))
{
document = await ApplyFixToDocumentAsync(document, diagnostic, cancellationToken).ConfigureAwait(false);
}

return document;
}

public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);
Expand All @@ -39,29 +56,40 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
Document document = context.Document;
Diagnostic diagnostic = context.Diagnostics[0];

switch (node)
string title = node switch
{
ImplicitArrayCreationExpressionSyntax => "Use explicitly typed array",
ArrayCreationExpressionSyntax => "Use implicitly typed array",
_ => throw new InvalidOperationException(),
};

CodeAction codeAction = CodeAction.Create(
title,
ct => ApplyFixToDocumentAsync(document, diagnostic, ct),
GetEquivalenceKey(diagnostic));

context.RegisterCodeFix(codeAction, diagnostic);
}

public static async Task<Document> ApplyFixToDocumentAsync(Document document, Diagnostic diag, CancellationToken cancellationToken)
{
SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

if (!TryFindFirstAncestorOrSelf(
root,
diag.Location.SourceSpan,
out SyntaxNode node,
predicate: f => f.IsKind(SyntaxKind.ImplicitArrayCreationExpression, SyntaxKind.ArrayCreationExpression)))
{
case ImplicitArrayCreationExpressionSyntax implicitArrayCreation:
{
CodeAction codeAction = CodeAction.Create(
"Use explicitly typed array",
ct => ChangeArrayTypeToExplicitAsync(document, implicitArrayCreation, ct),
GetEquivalenceKey(diagnostic));

context.RegisterCodeFix(codeAction, diagnostic);
break;
}
case ArrayCreationExpressionSyntax arrayCreation:
{
CodeAction codeAction = CodeAction.Create(
"Use implicitly typed array",
ct => ChangeArrayTypeToImplicitAsync(document, arrayCreation, ct),
GetEquivalenceKey(diagnostic));

context.RegisterCodeFix(codeAction, diagnostic);
break;
}
return null;
}

return node switch
{
ImplicitArrayCreationExpressionSyntax implicitArrayCreation => await ChangeArrayTypeToExplicitAsync(document, implicitArrayCreation, cancellationToken).ConfigureAwait(false),
ArrayCreationExpressionSyntax arrayCreation => await ChangeArrayTypeToImplicitAsync(document, arrayCreation, cancellationToken).ConfigureAwait(false),
_ => throw new InvalidOperationException()
};
}

private static async Task<Document> ChangeArrayTypeToExplicitAsync(
Expand Down Expand Up @@ -101,13 +129,10 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
ArrayCreationExpressionSyntax arrayCreation,
CancellationToken cancellationToken)
{
SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

ArrayTypeSyntax arrayType = arrayCreation.Type;
SyntaxList<ArrayRankSpecifierSyntax> rankSpecifiers = arrayType.RankSpecifiers;
InitializerExpressionSyntax initializer = arrayCreation.Initializer;

ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(arrayType.ElementType, cancellationToken);
TypeSyntax castType;

if (rankSpecifiers.Count > 1)
Expand Down

0 comments on commit 47b002c

Please sign in to comment.