@@ -17,11 +17,72 @@ import '../project.dart';
17
17
import 'test_time_recorder.dart' ;
18
18
19
19
/// A request to the [TestCompiler] for recompilation.
20
- class CompilationRequest {
21
- CompilationRequest (this .mainUri, this .result );
20
+ final class _CompilationRequest {
21
+ _CompilationRequest (this .mainUri);
22
22
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
+ }
25
86
}
26
87
27
88
/// A frontend_server wrapper for the flutter test runner.
@@ -79,9 +140,9 @@ class TestCompiler {
79
140
);
80
141
}
81
142
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 > [];
85
146
final FlutterProject ? flutterProject;
86
147
final BuildInfo buildInfo;
87
148
final String testFilePath;
@@ -91,13 +152,14 @@ class TestCompiler {
91
152
ResidentCompiler ? compiler;
92
153
late File outputDill;
93
154
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) {
96
157
if (compilerController.isClosed) {
97
- return Future < String ?>. value ( );
158
+ throw StateError ( 'TestCompiler is already disposed.' );
98
159
}
99
- compilerController.add (CompilationRequest (mainDart, completer));
100
- return completer.future;
160
+ final _CompilationRequest request = _CompilationRequest (dartEntrypointPath);
161
+ compilerController.add (request);
162
+ return request.result;
101
163
}
102
164
103
165
Future <void > _shutdown () async {
@@ -139,7 +201,7 @@ class TestCompiler {
139
201
}
140
202
141
203
// Handle a compilation request.
142
- Future <void > _onCompilationRequest (CompilationRequest request) async {
204
+ Future <void > _onCompilationRequest (_CompilationRequest request) async {
143
205
final bool isEmpty = compilationQueue.isEmpty;
144
206
compilationQueue.add (request);
145
207
// Only trigger processing if queue was empty - i.e. no other requests
@@ -149,7 +211,7 @@ class TestCompiler {
149
211
return ;
150
212
}
151
213
while (compilationQueue.isNotEmpty) {
152
- final CompilationRequest request = compilationQueue.first;
214
+ final _CompilationRequest request = compilationQueue.first;
153
215
globals.printTrace ('Compiling ${request .mainUri }' );
154
216
final Stopwatch compilerTime = Stopwatch ()..start ();
155
217
final Stopwatch ? testTimeRecorderStopwatch = testTimeRecorder? .start (TestTimePhases .Compile );
@@ -190,7 +252,12 @@ class TestCompiler {
190
252
// compiler to avoid reusing compiler that might have gotten into
191
253
// a weird state.
192
254
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
+ );
194
261
await _shutdown ();
195
262
} else {
196
263
if (shouldCopyDillFile) {
@@ -209,9 +276,13 @@ class TestCompiler {
209
276
}
210
277
await outputFile.copy (testFilePath);
211
278
}
212
- request.result.complete (kernelReadyToRun.path);
279
+ request._result.complete (
280
+ TestCompilerComplete (outputPath: kernelReadyToRun.path, mainUri: request.mainUri),
281
+ );
213
282
} else {
214
- request.result.complete (outputPath);
283
+ request._result.complete (
284
+ TestCompilerComplete (outputPath: outputPath, mainUri: request.mainUri),
285
+ );
215
286
}
216
287
compiler! .accept ();
217
288
compiler! .reset ();
0 commit comments