| Index: lib/src/codegen/js_printer.dart
|
| diff --git a/lib/src/codegen/js_printer.dart b/lib/src/codegen/js_printer.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..01dfb7544d520cc7777b109048f6c5eab841fa3b
|
| --- /dev/null
|
| +++ b/lib/src/codegen/js_printer.dart
|
| @@ -0,0 +1,109 @@
|
| +// 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.
|
| +
|
| +library dev_compiler.src.codegen.js_printer;
|
| +
|
| +import 'dart:io' show Directory, File;
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| +import 'package:path/path.dart' as path;
|
| +import 'package:source_maps/source_maps.dart' as srcmaps show Printer;
|
| +import 'package:source_maps/source_maps.dart' show SourceMapSpan;
|
| +import 'package:source_span/source_span.dart' show SourceLocation;
|
| +
|
| +import 'package:dev_compiler/src/js/js_ast.dart' as JS;
|
| +import 'package:dev_compiler/src/utils.dart'
|
| + show computeHash, locationForOffset;
|
| +
|
| +import 'js_names.dart' show JSNamer;
|
| +
|
| +String writeJsLibrary(JS.Program jsTree, String outputPath,
|
| + {bool emitSourceMaps: false}) {
|
| + new Directory(path.dirname(outputPath)).createSync(recursive: true);
|
| + if (emitSourceMaps) {
|
| + var outFilename = path.basename(outputPath);
|
| + var printer = new srcmaps.Printer(outFilename);
|
| + writeNodeToContext(jsTree,
|
| + new SourceMapPrintingContext(printer, path.dirname(outputPath)));
|
| + printer.add('//# sourceMappingURL=$outFilename.map');
|
| + // Write output file and source map
|
| + var text = printer.text;
|
| + new File(outputPath).writeAsStringSync(text);
|
| + new File('$outputPath.map').writeAsStringSync(printer.map);
|
| + return computeHash(text);
|
| + } else {
|
| + var text = jsNodeToString(jsTree);
|
| + new File(outputPath).writeAsStringSync(text);
|
| + return computeHash(text);
|
| + }
|
| +}
|
| +
|
| +void writeNodeToContext(JS.Node node, JS.JavaScriptPrintingContext context) {
|
| + var opts = new JS.JavaScriptPrintingOptions(allowKeywordsInProperties: true);
|
| + node.accept(new JS.Printer(opts, context, localNamer: new JSNamer(node)));
|
| +}
|
| +
|
| +String jsNodeToString(JS.Node node) {
|
| + var context = new JS.SimpleJavaScriptPrintingContext();
|
| + writeNodeToContext(node, context);
|
| + return context.getText();
|
| +}
|
| +
|
| +class SourceMapPrintingContext extends JS.JavaScriptPrintingContext {
|
| + final srcmaps.Printer printer;
|
| + final String outputDir;
|
| +
|
| + CompilationUnit unit;
|
| + Uri uri;
|
| +
|
| + SourceMapPrintingContext(this.printer, this.outputDir);
|
| +
|
| + void emit(String string) {
|
| + printer.add(string);
|
| + }
|
| +
|
| + void enterNode(JS.Node jsNode) {
|
| + AstNode node = jsNode.sourceInformation;
|
| + if (node is CompilationUnit) {
|
| + unit = node;
|
| + uri = _makeRelativeUri(unit.element.source.uri);
|
| + return;
|
| + }
|
| + if (unit == null || node == null || node.offset == -1) return;
|
| +
|
| + var loc = _location(node.offset);
|
| + var name = _getIdentifier(node);
|
| + if (name != null) {
|
| + // TODO(jmesserly): mark only uses the beginning of the span, but
|
| + // we're required to pass this as a valid span.
|
| + var end = _location(node.end);
|
| + printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true));
|
| + } else {
|
| + printer.mark(loc);
|
| + }
|
| + }
|
| +
|
| + SourceLocation _location(int offset) => locationForOffset(unit, uri, offset);
|
| +
|
| + Uri _makeRelativeUri(Uri src) {
|
| + return new Uri(path: path.relative(src.path, from: outputDir));
|
| + }
|
| +
|
| + void exitNode(JS.Node jsNode) {
|
| + AstNode node = jsNode.sourceInformation;
|
| + if (node is CompilationUnit) {
|
| + unit = null;
|
| + uri = null;
|
| + return;
|
| + }
|
| + if (unit == null || node == null || node.offset == -1) return;
|
| +
|
| + // TODO(jmesserly): in many cases marking the end will be unnecessary.
|
| + printer.mark(_location(node.end));
|
| + }
|
| +
|
| + String _getIdentifier(AstNode node) {
|
| + if (node is SimpleIdentifier) return node.name;
|
| + return null;
|
| + }
|
| +}
|
|
|