Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: lib/src/codegen/js_printer.dart

Issue 1879373004: Implement modular compilation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/codegen/js_names.dart ('k') | lib/src/codegen/js_typeref_codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:convert' show JSON, JsonEncoder;
6 import 'dart:io' show Directory, File, Platform, Process;
7
8 import 'package:analyzer/dart/ast/ast.dart';
9 import 'package:path/path.dart' as path;
10 import 'package:source_maps/source_maps.dart' as srcmaps show Printer;
11 import 'package:source_maps/source_maps.dart' show SourceMapSpan;
12 import 'package:source_span/source_span.dart' show SourceLocation;
13
14 import '../js/js_ast.dart' as JS;
15 import '../utils.dart' show FileSystem, computeHash, locationForOffset;
16
17 import 'js_names.dart' show TemporaryNamer;
18
19 void writeJsLibrary(JS.Program jsTree, String outputPath, String inputDir,
20 {bool emitSourceMaps: false,
21 bool emitTypes: false,
22 FileSystem fileSystem}) {
23 var outFilename = path.basename(outputPath);
24 var outDir = path.dirname(outputPath);
25
26 JS.JavaScriptPrintingContext context;
27 if (emitSourceMaps) {
28 var printer = new srcmaps.Printer(outFilename);
29 context = new SourceMapPrintingContext(printer, outDir, inputDir, null);
30 } else {
31 context = new JS.SimpleJavaScriptPrintingContext();
32 }
33
34 var opts = new JS.JavaScriptPrintingOptions(
35 emitTypes: emitTypes,
36 allowKeywordsInProperties: true,
37 allowSingleLineIfStatements: true);
38 var jsNamer = new TemporaryNamer(jsTree);
39 jsTree.accept(new JS.Printer(opts, context, localNamer: jsNamer));
40
41 String text;
42 if (context is SourceMapPrintingContext) {
43 var printer = context.printer;
44 printer.add('//# sourceMappingURL=$outFilename.map\n');
45 // Write output file and source map
46 text = printer.text;
47 var sourceMap = JSON.decode(printer.map);
48 // TODO(jmesserly): I'm not sure where this logic came from, but we should
49 // upstream this, rather than workaround source_map's formatting ourselves.
50 var sourceMapText = new JsonEncoder.withIndent(' ').convert(sourceMap);
51 // Convert:
52 // "names": [
53 // "state",
54 // "print"
55 // ]
56 // to:
57 // "names": ["state","print"]
58 sourceMapText =
59 sourceMapText.replaceAll('\n ', '').replaceAll('\n ]', ']');
60 fileSystem.writeAsStringSync('$outputPath.map', '$sourceMapText\n');
61 } else {
62 text = (context as JS.SimpleJavaScriptPrintingContext).getText();
63 }
64 fileSystem.writeAsStringSync(outputPath, text);
65 if (jsTree.scriptTag != null) {
66 // Mark executable.
67 // TODO(jmesserly): should only do this if the input file was executable?
68 if (!Platform.isWindows) Process.runSync('chmod', ['+x', outputPath]);
69 }
70 }
71
72 class SourceMapPrintingContext extends JS.JavaScriptPrintingContext {
73 final srcmaps.Printer printer;
74 final String outputDir;
75 final String inputDir;
76
77 final Uri baseUri;
78
79 CompilationUnit unit;
80 Uri uri;
81
82 SourceMapPrintingContext(
83 this.printer, this.outputDir, this.inputDir, this.baseUri);
84
85 void emit(String string) {
86 printer.add(string);
87 }
88
89 AstNode _currentTopLevelDeclaration;
90
91 void enterNode(JS.Node jsNode) {
92 AstNode node = jsNode.sourceInformation;
93 if (node == null || node.offset == -1) return;
94 if (unit == null) {
95 // This is a top-level declaration. Note: consecutive top-level
96 // declarations may come from different compilation units due to
97 // parts.
98 _currentTopLevelDeclaration = node;
99 unit = node.getAncestor((n) => n is CompilationUnit);
100 uri = _makeRelativeUri(unit.element.source.uri);
101 }
102 if (unit == null) return;
103
104 assert(unit != null);
105 var loc = _location(node.offset);
106 var name = _getIdentifier(node);
107 if (name != null) {
108 // TODO(jmesserly): mark only uses the beginning of the span, but
109 // we're required to pass this as a valid span.
110 var end = _location(node.end);
111 printer.mark(new SourceMapSpan(loc, end, name, isIdentifier: true));
112 } else {
113 printer.mark(loc);
114 }
115 }
116
117 SourceLocation _location(int offset) =>
118 locationForOffset(unit.lineInfo, uri, offset);
119
120 Uri _makeRelativeUri(Uri src) {
121 if (baseUri == null) {
122 return new Uri(path: path.relative(src.path, from: outputDir));
123 } else {
124 if (src.path.startsWith('/')) {
125 return baseUri.resolve(path.relative(src.path, from: inputDir));
126 } else {
127 return baseUri.resolve(path.join('packages', src.path));
128 }
129 }
130 }
131
132 void exitNode(JS.Node jsNode) {
133 AstNode node = jsNode.sourceInformation;
134 if (unit == null || node == null || node.offset == -1) return;
135
136 // TODO(jmesserly): in many cases marking the end will be unnecessary.
137 printer.mark(_location(node.end));
138
139 if (_currentTopLevelDeclaration == node) {
140 unit = null;
141 uri = null;
142 _currentTopLevelDeclaration == null;
143 return;
144 }
145 }
146
147 String _getIdentifier(AstNode node) {
148 if (node is SimpleIdentifier) return node.name;
149 return null;
150 }
151 }
OLDNEW
« no previous file with comments | « lib/src/codegen/js_names.dart ('k') | lib/src/codegen/js_typeref_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698