| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // Output provider that collects the output in string buffers. |
| |
| library; |
| |
| import 'package:compiler/compiler_api.dart' as api; |
| |
| class BufferedOutputSink implements api.OutputSink { |
| StringBuffer? sb = StringBuffer(); |
| String? text; |
| |
| @override |
| void add(String event) { |
| sb!.write(event); |
| } |
| |
| @override |
| void close() { |
| text = sb.toString(); |
| sb = null; |
| } |
| |
| @override |
| String toString() { |
| return text ?? sb.toString(); |
| } |
| } |
| |
| class BufferedBinaryOutputSink implements api.BinaryOutputSink { |
| final Uri uri; |
| |
| List<int> list = <int>[]; |
| |
| BufferedBinaryOutputSink(this.uri); |
| |
| @override |
| void add(List<int> buffer, [int start = 0, int? end]) { |
| list.addAll(buffer.sublist(start, end)); |
| } |
| |
| @override |
| void close() {} |
| |
| @override |
| String toString() { |
| return 'BufferedBinaryOutputSink($uri)'; |
| } |
| } |
| |
| class CloningOutputSink implements api.OutputSink { |
| final List<api.OutputSink> sinks; |
| |
| CloningOutputSink(this.sinks); |
| |
| @override |
| void add(String event) { |
| for (var sink in sinks) { |
| sink.add(event); |
| } |
| } |
| |
| @override |
| void close() { |
| for (var sink in sinks) { |
| sink.close(); |
| } |
| } |
| } |
| |
| class OutputCollector implements api.CompilerOutput { |
| Map<api.OutputType, Map<String, BufferedOutputSink>> outputMap = {}; |
| Map<Uri, BufferedBinaryOutputSink> binaryOutputMap = {}; |
| |
| String? getOutput(String name, api.OutputType type) { |
| Map<String, BufferedOutputSink>? sinkMap = outputMap[type]; |
| if (sinkMap == null) { |
| print("No output available for $type."); |
| return null; |
| } |
| BufferedOutputSink? sink = sinkMap[name]; |
| if (sink == null) { |
| print("Output '$name' not found for $type. Available: ${sinkMap.keys}"); |
| return null; |
| } else { |
| return sink.text; |
| } |
| } |
| |
| @override |
| api.BinaryOutputSink createBinarySink(Uri uri) { |
| return binaryOutputMap.putIfAbsent( |
| uri, |
| () => BufferedBinaryOutputSink(uri), |
| ); |
| } |
| |
| /// `true` if any output has been collected. |
| bool get hasOutput => outputMap.isNotEmpty || binaryOutputMap.isNotEmpty; |
| |
| /// `true` if any output other than main output has been collected. |
| bool get hasExtraOutput { |
| for (Map<String, BufferedOutputSink> output in outputMap.values) { |
| for (String name in output.keys) { |
| if (name != '') return true; |
| } |
| } |
| return binaryOutputMap.isNotEmpty; |
| } |
| |
| @override |
| api.OutputSink createOutputSink( |
| String name, |
| String extension, |
| api.OutputType type, |
| ) { |
| Map<String, BufferedOutputSink> sinkMap = outputMap.putIfAbsent( |
| type, |
| () => {}, |
| ); |
| return sinkMap.putIfAbsent(name, () => BufferedOutputSink()); |
| } |
| |
| Map<api.OutputType, Map<String, String>> clear() { |
| Map<api.OutputType, Map<String, String>> outputMapResult = {}; |
| outputMap.forEach(( |
| api.OutputType outputType, |
| Map<String, BufferedOutputSink> sinkMap, |
| ) { |
| Map<String, String> sinkMapResult = outputMapResult[outputType] = {}; |
| sinkMap.forEach((String name, BufferedOutputSink sink) { |
| sinkMapResult[name] = sink.toString(); |
| }); |
| }); |
| outputMap.clear(); |
| binaryOutputMap.clear(); |
| return outputMapResult; |
| } |
| } |