1+ // -----------------------------------------------------------------------
2+ // <copyright file="ShouldNotUseSystemToCreateChildActorsAnalyzerSpecs.cs" company="Akka.NET Project">
3+ // Copyright (C) 2013-2025 .NET Foundation <https://github.com/akkadotnet/akka.net>
4+ // </copyright>
5+ // -----------------------------------------------------------------------
6+
7+ using Microsoft . CodeAnalysis ;
8+ using Verify = Akka . Analyzers . Tests . Utility . AkkaVerifier < Akka . Analyzers . ShouldNotUseSystemToCreateChildActorsAnalyzer > ;
9+
10+ namespace Akka . Analyzers . Tests . Analyzers . AK1000 ;
11+
12+ public class ShouldNotUseSystemToCreateChildActorsAnalyzerSpecs
13+ {
14+ public static readonly TheoryData < string > SuccessCases = new ( )
15+ {
16+ // Non-actor class uses ActorSystem to create an actor
17+ """
18+ using Akka.Actor;
19+
20+ public class SaveClass
21+ {
22+ public SaveClass(ActorSystem system)
23+ {
24+ system.ActorOf(Props.Create(() => new ChildActor())); // Shouldn't flag this
25+ system.ActorOf<ChildActor>(); // Shouldn't flag this
26+ }
27+ }
28+
29+ public class ChildActor : ReceiveActor
30+ {
31+ }
32+ """ ,
33+
34+ // Actors using Context to create child actors
35+ """
36+ using Akka.Actor;
37+
38+ public class MyActor : ReceiveActor
39+ {
40+ public MyActor()
41+ {
42+ Context.ActorOf(Props.Create(() => new ChildActor())); // Shouldn't flag this
43+ Context.ActorOf<ChildActor>(); // Shouldn't flag this
44+ }
45+ }
46+
47+ public class ChildActor : ReceiveActor
48+ {
49+ }
50+ """ ,
51+ } ;
52+
53+ public static readonly
54+ TheoryData < ( string testData , ( int startLine , int startColumn , int endLine , int endColumn ) spanData ) >
55+ FailureCases = new ( )
56+ {
57+ // ReceiveActor invoking ActorSystem.ActorOf() directly
58+ (
59+ """
60+ // 01
61+ using Akka.Actor;
62+
63+ public class MyActor : ReceiveActor
64+ {
65+ public MyActor(ActorSystem system)
66+ {
67+ system.ActorOf(Props.Create(() => new ChildActor()));
68+ }
69+ }
70+
71+ public class ChildActor : ReceiveActor
72+ {
73+ }
74+ """ , ( 8 , 9 , 8 , 61 ) ) ,
75+
76+ // ReceiveActor invoking Context.System.ActorOf()
77+ (
78+ """
79+ // 02
80+ using Akka.Actor;
81+
82+ public class MyActor : ReceiveActor
83+ {
84+ public MyActor()
85+ {
86+ Context.System.ActorOf(Props.Create(() => new ChildActor()));
87+ }
88+ }
89+
90+ public class ChildActor : ReceiveActor
91+ {
92+ }
93+ """ , ( 8 , 9 , 8 , 69 ) ) ,
94+
95+ // ReceiveActor invoking ActorOf<T>() extension on ActorSystem directly
96+ (
97+ """
98+ // 03
99+ using Akka.Actor;
100+
101+ public class MyActor : ReceiveActor
102+ {
103+ public MyActor(ActorSystem system)
104+ {
105+ system.ActorOf<ChildActor>();
106+ }
107+ }
108+
109+ public class ChildActor : ReceiveActor
110+ {
111+ }
112+ """ , ( 8 , 9 , 8 , 37 ) ) ,
113+
114+ // ReceiveActor invoking ActorOf<T>() extension on Context.System
115+ (
116+ """
117+ // 04
118+ using Akka.Actor;
119+
120+ public class MyActor : ReceiveActor
121+ {
122+ public MyActor()
123+ {
124+ Context.System.ActorOf<ChildActor>();
125+ }
126+ }
127+
128+ public class ChildActor : ReceiveActor
129+ {
130+ }
131+ """ , ( 8 , 9 , 8 , 45 ) ) ,
132+
133+
134+ // UntypedActor invoking ActorSystem.ActorOf() directly
135+ (
136+ """
137+ // 05
138+ using Akka.Actor;
139+
140+ public class MyActor : UntypedActor
141+ {
142+ public MyActor(ActorSystem system)
143+ {
144+ system.ActorOf(Props.Create(() => new ChildActor()));
145+ }
146+
147+ protected override void OnReceive(object message)
148+ {
149+ throw new System.NotImplementedException();
150+ }
151+ }
152+
153+ public class ChildActor : ReceiveActor
154+ {
155+ }
156+ """ , ( 8 , 9 , 8 , 61 ) ) ,
157+
158+ // UntypedActor invoking Context.System.ActorOf()
159+ (
160+ """
161+ // 06
162+ using Akka.Actor;
163+
164+ public class MyActor : UntypedActor
165+ {
166+ public MyActor()
167+ {
168+ Context.System.ActorOf(Props.Create(() => new ChildActor()));
169+ }
170+
171+ protected override void OnReceive(object message)
172+ {
173+ throw new System.NotImplementedException();
174+ }
175+ }
176+
177+ public class ChildActor : ReceiveActor
178+ {
179+ }
180+ """ , ( 8 , 9 , 8 , 69 ) ) ,
181+
182+ // UntypedActor invoking ActorOf<T>() extension on ActorSystem directly
183+ (
184+ """
185+ // 07
186+ using Akka.Actor;
187+
188+ public class MyActor : UntypedActor
189+ {
190+ public MyActor(ActorSystem system)
191+ {
192+ system.ActorOf<ChildActor>();
193+ }
194+
195+ protected override void OnReceive(object message)
196+ {
197+ throw new System.NotImplementedException();
198+ }
199+ }
200+
201+ public class ChildActor : ReceiveActor
202+ {
203+ }
204+ """ , ( 8 , 9 , 8 , 37 ) ) ,
205+
206+ // UntypedActor invoking ActorOf<T>() extension on Context.System
207+ (
208+ """
209+ // 08
210+ using Akka.Actor;
211+
212+ public class MyActor : UntypedActor
213+ {
214+ public MyActor()
215+ {
216+ Context.System.ActorOf<ChildActor>();
217+ }
218+
219+ protected override void OnReceive(object message)
220+ {
221+ throw new System.NotImplementedException();
222+ }
223+ }
224+
225+ public class ChildActor : ReceiveActor
226+ {
227+ }
228+ """ , ( 8 , 9 , 8 , 45 ) ) ,
229+ } ;
230+
231+ [ Theory ]
232+ [ MemberData ( nameof ( SuccessCases ) ) ]
233+ public async Task SuccessCase ( string testCode )
234+ {
235+ await Verify . VerifyAnalyzer ( testCode ) . ConfigureAwait ( true ) ;
236+ }
237+
238+ [ Theory ]
239+ [ MemberData ( nameof ( FailureCases ) ) ]
240+ public Task FailureCase (
241+ ( string testCode , ( int startLine , int startColumn , int endLine , int endColumn ) spanData ) d )
242+ {
243+ var expected = Verify . Diagnostic ( )
244+ . WithSpan ( d . spanData . startLine , d . spanData . startColumn , d . spanData . endLine , d . spanData . endColumn )
245+ . WithSeverity ( DiagnosticSeverity . Warning ) ;
246+
247+ return Verify . VerifyAnalyzer ( d . testCode , expected ) ;
248+ }
249+
250+ }
0 commit comments