@@ -17,11 +17,72 @@ import '../project.dart';
1717import 'test_time_recorder.dart' ;
1818
1919/// A request to the [TestCompiler] for recompilation.
20- class CompilationRequest {
21- CompilationRequest (this .mainUri, this .result );
20+ final class _CompilationRequest {
21+ _CompilationRequest (this .mainUri);
2222
23- Uri mainUri;
24- Completer <String ?> result;
23+ /// The entrypoint (containing `main()` ) to the Dart program being compiled.
24+ final Uri mainUri;
25+
26+ /// Invoked when compilation is completed with the compilation output path.
27+ Future <TestCompilerResult > get result => _result.future;
28+ final Completer <TestCompilerResult > _result = Completer <TestCompilerResult >();
29+ }
30+
31+ /// The result of [TestCompiler.compile] .
32+ @immutable
33+ sealed class TestCompilerResult {
34+ const TestCompilerResult ({required this .mainUri});
35+
36+ /// The program that was or was attempted to be compiled.
37+ final Uri mainUri;
38+ }
39+
40+ /// A successful run of [TestCompiler.compile] .
41+ final class TestCompilerComplete extends TestCompilerResult {
42+ const TestCompilerComplete ({required this .outputPath, required super .mainUri});
43+
44+ /// Output path of the compiled program.
45+ final String outputPath;
46+
47+ @override
48+ bool operator == (Object other) {
49+ if (other is ! TestCompilerComplete ) {
50+ return false ;
51+ }
52+ return mainUri == other.mainUri && outputPath == other.outputPath;
53+ }
54+
55+ @override
56+ int get hashCode => Object .hash (mainUri, outputPath);
57+
58+ @override
59+ String toString () {
60+ return 'TestCompilerComplete(mainUri: $mainUri , outputPath: $outputPath )' ;
61+ }
62+ }
63+
64+ /// A failed run of [TestCompiler.compile] .
65+ final class TestCompilerFailure extends TestCompilerResult {
66+ const TestCompilerFailure ({required this .error, required super .mainUri});
67+
68+ /// Error message that occurred failing compilation.
69+ final String error;
70+
71+ @override
72+ bool operator == (Object other) {
73+ if (other is ! TestCompilerFailure ) {
74+ return false ;
75+ }
76+ return mainUri == other.mainUri && error == other.error;
77+ }
78+
79+ @override
80+ int get hashCode => Object .hash (mainUri, error);
81+
82+ @override
83+ String toString () {
84+ return 'TestCompilerComplete(mainUri: $mainUri , error: $error )' ;
85+ }
2586}
2687
2788/// A frontend_server wrapper for the flutter test runner.
@@ -79,9 +140,9 @@ class TestCompiler {
79140 );
80141 }
81142
82- final StreamController <CompilationRequest > compilerController =
83- StreamController <CompilationRequest >();
84- final List <CompilationRequest > compilationQueue = < CompilationRequest > [];
143+ final StreamController <_CompilationRequest > compilerController =
144+ StreamController <_CompilationRequest >();
145+ final List <_CompilationRequest > compilationQueue = < _CompilationRequest > [];
85146 final FlutterProject ? flutterProject;
86147 final BuildInfo buildInfo;
87148 final String testFilePath;
@@ -91,13 +152,14 @@ class TestCompiler {
91152 ResidentCompiler ? compiler;
92153 late File outputDill;
93154
94- Future < String ?> compile ( Uri mainDart) {
95- final Completer < String ?> completer = Completer < String ?>();
155+ /// Compiles the Dart program (an entrypoint containing `main()` ).
156+ Future < TestCompilerResult > compile ( Uri dartEntrypointPath) {
96157 if (compilerController.isClosed) {
97- return Future < String ?>. value ( );
158+ throw StateError ( 'TestCompiler is already disposed.' );
98159 }
99- compilerController.add (CompilationRequest (mainDart, completer));
100- return completer.future;
160+ final _CompilationRequest request = _CompilationRequest (dartEntrypointPath);
161+ compilerController.add (request);
162+ return request.result;
101163 }
102164
103165 Future <void > _shutdown () async {
@@ -139,7 +201,7 @@ class TestCompiler {
139201 }
140202
141203 // Handle a compilation request.
142- Future <void > _onCompilationRequest (CompilationRequest request) async {
204+ Future <void > _onCompilationRequest (_CompilationRequest request) async {
143205 final bool isEmpty = compilationQueue.isEmpty;
144206 compilationQueue.add (request);
145207 // Only trigger processing if queue was empty - i.e. no other requests
@@ -149,7 +211,7 @@ class TestCompiler {
149211 return ;
150212 }
151213 while (compilationQueue.isNotEmpty) {
152- final CompilationRequest request = compilationQueue.first;
214+ final _CompilationRequest request = compilationQueue.first;
153215 globals.printTrace ('Compiling ${request .mainUri }' );
154216 final Stopwatch compilerTime = Stopwatch ()..start ();
155217 final Stopwatch ? testTimeRecorderStopwatch = testTimeRecorder? .start (TestTimePhases .Compile );
@@ -190,7 +252,12 @@ class TestCompiler {
190252 // compiler to avoid reusing compiler that might have gotten into
191253 // a weird state.
192254 if (outputPath == null || compilerOutput! .errorCount > 0 ) {
193- request.result.complete ();
255+ request._result.complete (
256+ TestCompilerFailure (
257+ error: compilerOutput! .errorMessage ?? 'Unknown Error' ,
258+ mainUri: request.mainUri,
259+ ),
260+ );
194261 await _shutdown ();
195262 } else {
196263 if (shouldCopyDillFile) {
@@ -209,9 +276,13 @@ class TestCompiler {
209276 }
210277 await outputFile.copy (testFilePath);
211278 }
212- request.result.complete (kernelReadyToRun.path);
279+ request._result.complete (
280+ TestCompilerComplete (outputPath: kernelReadyToRun.path, mainUri: request.mainUri),
281+ );
213282 } else {
214- request.result.complete (outputPath);
283+ request._result.complete (
284+ TestCompilerComplete (outputPath: outputPath, mainUri: request.mainUri),
285+ );
215286 }
216287 compiler! .accept ();
217288 compiler! .reset ();
0 commit comments