Skip to content

Commit

Permalink
AK2001: detect when automatically handled messages are being handled …
Browse files Browse the repository at this point in the history
…inside MessageExtractor / IMessageExtractor (#43)
  • Loading branch information
Aaronontheweb authored Jan 8, 2024
1 parent 7c675aa commit 95d6a95
Show file tree
Hide file tree
Showing 12 changed files with 1,343 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// -----------------------------------------------------------------------
// <copyright file="MustNotUseAutomaticallyHandledMessagesInsideMessageExtractorFixer.cs" company="Akka.NET Project">
// Copyright (C) 2013-2024 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using IfStatementSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.IfStatementSyntax;

namespace Akka.Analyzers.Fixes;

[ExportCodeFixProvider(LanguageNames.CSharp)]
[Shared]
public class MustNotUseAutomaticallyHandledMessagesInsideMessageExtractorFixer()
: BatchedCodeFixProvider(RuleDescriptors.Ak2001DoNotUseAutomaticallyHandledMessagesInShardMessageExtractor.Id)
{
public const string Key_FixAutomaticallyHandledShardedMessage = "AK2001_FixAutoShardMessage";

public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root is null)
return;

var reportedNodes = new HashSet<SyntaxNode>();

foreach (var diagnostic in context.Diagnostics)
{
var diagnosticSpan = diagnostic.Location.SourceSpan;

// Find the token at the location of the diagnostic.
var token = root.FindToken(diagnosticSpan.Start);

// Find the correct parent node to remove.
var nodeToRemove = FindParentNodeToRemove(token.Parent);

// Check if the node has already been processed to avoid duplicates
if (nodeToRemove != null && reportedNodes.Add(nodeToRemove))
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Remove unnecessary message handling",
createChangedDocument: c => RemoveOffendingNode(context.Document, nodeToRemove, c),
equivalenceKey: Key_FixAutomaticallyHandledShardedMessage),
diagnostic);
}
}
}

private static SyntaxNode? FindParentNodeToRemove(SyntaxNode? node)
{
while (node != null)
{
if (node is IfStatementSyntax || node is SwitchSectionSyntax || node is SwitchExpressionArmSyntax)
{
// special case - have to check for else if here
if(node.Parent is ElseClauseSyntax)
return node.Parent;
return node;
}
node = node.Parent;
}
return null;
}

private static async Task<Document> RemoveOffendingNode(Document document, SyntaxNode nodeToRemove, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if(root == null)
return document;

var newRoot = root.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepNoTrivia);
return newRoot == null ? document : document.WithSyntaxRoot(newRoot);
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ak1000/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ak2000/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utility/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
3 changes: 3 additions & 0 deletions src/Akka.Analyzers.Tests/Akka.Analyzers.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

<ItemGroup>
<!-- Download packages referenced by ReferenceAssembliesHelper -->
<!-- TODO: are transitive references downloaded? If so we could trim this list to just Akka.Cluster.Sharding -->
<PackageDownload Include="Akka" Version="[1.5.14]"/>
<PackageDownload Include="Akka.Cluster.Sharding" Version="[1.5.14]"/>
<PackageDownload Include="Akka.Cluster" Version="[1.5.14]"/>
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 95d6a95

Please sign in to comment.