Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ak1001 Context.Sender fix #54

Merged
merged 7 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,18 @@ async Task<int> LocalFunction(){
LocalFunction().PipeTo(Sender);
}
}
"""
""",
// Replying to Sender using Context.Sender
@"using Akka.Actor;

public sealed class MyActor : ReceiveActor{

public MyActor(){
Receive<string>(str => {
Context.Sender.Tell(str); // shouldn't flag this
});
}
}",
};

public static readonly
Expand Down Expand Up @@ -194,4 +205,33 @@ public Task FailureCase(

return Verify.VerifyAnalyzer(d.testCode, expected);
}

[Fact(DisplayName = "Should detect missing closure when using Context.Sender instead of this.Sender")]
public Task FailureCaseWithContextSender()
{
var code = """
using Akka.Actor;
using System.Threading.Tasks;

public sealed class MyActor : UntypedActor{

protected override void OnReceive(object message){
async Task<int> LocalFunction(){
await Task.Delay(10);
return message.ToString().Length;
}

// incorrect use of closures
LocalFunction().PipeTo(Context.Sender);
}
}
""";

var expected = Verify.Diagnostic()
.WithSpan(13, 25, 13, 31)
.WithArguments("Context.Sender")
.WithSeverity(DiagnosticSeverity.Error);

return Verify.VerifyAnalyzer(code, expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// -----------------------------------------------------------------------

using Akka.Analyzers.Fixes;
using Microsoft.CodeAnalysis;
using Verify = Akka.Analyzers.Tests.Utility.AkkaVerifier<Akka.Analyzers.MustCloseOverSenderWhenUsingPipeToAnalyzer>;

namespace Akka.Analyzers.Tests.Fixes.AK1000;
Expand Down Expand Up @@ -260,4 +261,53 @@ async Task<int> LocalFunction(){
return Verify.VerifyCodeFix(before, after, MustCloseOverSenderWhenUsingPipeToFixer.Key_FixPipeToSender,
expectedDiagnostic);
}

[Fact(DisplayName = "Should fix missing closure when using Context.Sender instead of this.Sender")]
public Task FailureCaseWithContextSender()
{
var before = """
using Akka.Actor;
using System.Threading.Tasks;

public sealed class MyActor : UntypedActor{

protected override void OnReceive(object message){
async Task<int> LocalFunction(){
await Task.Delay(10);
return message.ToString().Length;
}

// incorrect use of closures
LocalFunction().PipeTo(Context.Sender);
}
}
""";

var after = """
using Akka.Actor;
using System.Threading.Tasks;

public sealed class MyActor : UntypedActor{

protected override void OnReceive(object message){
async Task<int> LocalFunction(){
await Task.Delay(10);
return message.ToString().Length;
}
var sender = this.Sender;

// incorrect use of closures
LocalFunction().PipeTo(sender);
}
}
""";

var expected = Verify.Diagnostic()
.WithSpan(13, 25, 13, 31)
.WithArguments("Context.Sender")
.WithSeverity(DiagnosticSeverity.Error);

return Verify.VerifyCodeFix(before, after, MustCloseOverSenderWhenUsingPipeToFixer.Key_FixPipeToSender,
expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ public override void AnalyzeCompilation(CompilationStartAnalysisContext context,

private static bool IsThisSenderSymbol(ISymbol? symbol, AkkaContext akkaContext)
{
// Check if the symbol is 'this.Sender'
return symbol is { Name: "Sender", ContainingType.BaseType: not null } &&
symbol.ContainingType.IsActorBaseSubclass(akkaContext);
// Check if the symbol is 'this.Sender' or 'Context.Sender'
return (symbol is { Name: "Sender", ContainingType.BaseType: not null } &&
symbol.ContainingType.IsActorBaseSubclass(akkaContext)) ||
(symbol is IPropertySymbol propertySymbol &&
propertySymbol.Name == "Sender" &&
SymbolEqualityComparer.Default.Equals(propertySymbol.ContainingType, akkaContext.AkkaCore.ActorContextType));
}
}