// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. library flutter_frontend_server; import 'dart:async'; import 'dart:io' hide FileSystemEntity; import 'package:args/args.dart'; import 'package:path/path.dart' as path; import 'package:vm/incremental_compiler.dart'; import 'package:frontend_server/frontend_server.dart' as frontend show FrontendCompiler, CompilerInterface, listenAndCompile, argParser, usage, ProgramTransformer; /// Wrapper around [FrontendCompiler] that adds [widgetCreatorTracker] kernel /// transformation to the compilation. class _FlutterFrontendCompiler implements frontend.CompilerInterface { final frontend.CompilerInterface _compiler; _FlutterFrontendCompiler(StringSink output, {bool unsafePackageSerialization, frontend.ProgramTransformer transformer}) : _compiler = frontend.FrontendCompiler(output, transformer: transformer, unsafePackageSerialization: unsafePackageSerialization); @override Future compile(String filename, ArgResults options, {IncrementalCompiler generator}) async { return _compiler.compile(filename, options, generator: generator); } @override Future recompileDelta({String entryPoint}) async { return _compiler.recompileDelta(entryPoint: entryPoint); } @override void acceptLastDelta() { _compiler.acceptLastDelta(); } @override Future rejectLastDelta() async { return _compiler.rejectLastDelta(); } @override void invalidate(Uri uri) { _compiler.invalidate(uri); } @override Future compileExpression( String expression, List definitions, List typeDefinitions, String libraryUri, String klass, bool isStatic) { return _compiler.compileExpression( expression, definitions, typeDefinitions, libraryUri, klass, isStatic); } @override void reportError(String msg) { _compiler.reportError(msg); } @override void resetIncrementalCompiler() { _compiler.resetIncrementalCompiler(); } } /// Entry point for this module, that creates `_FrontendCompiler` instance and /// processes user input. /// `compiler` is an optional parameter so it can be replaced with mocked /// version for testing. Future starter( List args, { frontend.CompilerInterface compiler, Stream> input, StringSink output, frontend.ProgramTransformer transformer, }) async { ArgResults options; try { options = frontend.argParser.parse(args); } catch (error) { print('ERROR: $error\n'); print(frontend.usage); return 1; } if (options['train']) { if (!options.rest.isNotEmpty) { throw Exception('Must specify input.dart'); } final String input = options.rest[0]; final String sdkRoot = options['sdk-root']; final Directory temp = Directory.systemTemp.createTempSync('train_frontend_server'); try { for (int i = 0; i < 3; i++) { final String outputTrainingDill = path.join(temp.path, 'app.dill'); options = frontend.argParser.parse([ '--incremental', '--sdk-root=$sdkRoot', '--output-dill=$outputTrainingDill', '--target=flutter', '--track-widget-creation', '--enable-asserts', '--gen-bytecode', '--bytecode-options=source-positions,local-var-info,debugger-stops,instance-field-initializers,keep-unreachable-code,avoid-closure-call-instructions', ]); compiler ??= _FlutterFrontendCompiler(output); await compiler.compile(input, options); compiler.acceptLastDelta(); await compiler.recompileDelta(); compiler.acceptLastDelta(); compiler.resetIncrementalCompiler(); await compiler.recompileDelta(); compiler.acceptLastDelta(); await compiler.recompileDelta(); compiler.acceptLastDelta(); } return 0; } finally { temp.deleteSync(recursive: true); } } compiler ??= _FlutterFrontendCompiler(output, transformer: transformer, unsafePackageSerialization: options['unsafe-package-serialization']); if (options.rest.isNotEmpty) { return await compiler.compile(options.rest[0], options) ? 0 : 254; } final Completer completer = Completer(); frontend.listenAndCompile(compiler, input ?? stdin, options, completer); return completer.future; }