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

Side by Side Diff: pkg/polymer/lib/src/compiler.dart

Issue 23445009: Prune the old deploy code. This CL does a few changes: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library compiler; 5 library compiler;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection' show SplayTreeMap; 8 import 'dart:collection' show SplayTreeMap;
9 import 'dart:json' as json; 9 import 'dart:json' as json;
10 10
11 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur iBasedDirective; 11 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur iBasedDirective;
12 import 'package:csslib/visitor.dart' show StyleSheet, treeToDebugString; 12 import 'package:csslib/visitor.dart' show StyleSheet, treeToDebugString;
13 import 'package:html5lib/dom.dart'; 13 import 'package:html5lib/dom.dart';
14 import 'package:html5lib/parser.dart'; 14 import 'package:html5lib/parser.dart';
15 import 'package:observe/transform.dart' show transformObservables;
16 import 'package:source_maps/span.dart' show Span; 15 import 'package:source_maps/span.dart' show Span;
17 import 'package:source_maps/refactor.dart' show TextEditTransaction; 16 import 'package:source_maps/refactor.dart' show TextEditTransaction;
18 import 'package:source_maps/printer.dart'; 17 import 'package:source_maps/printer.dart';
19 18
20 import 'analyzer.dart'; 19 import 'analyzer.dart';
21 import 'css_analyzer.dart' show analyzeCss, findUrlsImported, 20 import 'css_analyzer.dart' show analyzeCss, findUrlsImported,
22 findImportsInStyleSheet, parseCss; 21 findImportsInStyleSheet, parseCss;
23 import 'css_emitters.dart' show rewriteCssUris, 22 import 'css_emitters.dart' show rewriteCssUris,
24 emitComponentStyleSheet, emitOriginalCss, emitStyleSheet; 23 emitComponentStyleSheet, emitOriginalCss, emitStyleSheet;
25 import 'dart_parser.dart'; 24 import 'dart_parser.dart';
26 import 'emitters.dart';
27 import 'file_system.dart'; 25 import 'file_system.dart';
28 import 'files.dart'; 26 import 'files.dart';
29 import 'info.dart'; 27 import 'info.dart';
30 import 'messages.dart'; 28 import 'messages.dart';
31 import 'compiler_options.dart'; 29 import 'compiler_options.dart';
32 import 'paths.dart';
33 import 'utils.dart'; 30 import 'utils.dart';
34 31
35 /** 32 /**
36 * Parses an HTML file [contents] and returns a DOM-like tree. 33 * Parses an HTML file [contents] and returns a DOM-like tree.
37 * Note that [contents] will be a [String] if coming from a browser-based 34 * Note that [contents] will be a [String] if coming from a browser-based
38 * [FileSystem], or it will be a [List<int>] if running on the command line. 35 * [FileSystem], or it will be a [List<int>] if running on the command line.
39 * 36 *
40 * Adds emitted error/warning to [messages], if [messages] is supplied. 37 * Adds emitted error/warning to [messages], if [messages] is supplied.
41 */ 38 */
42 Document parseHtml(contents, String sourcePath, Messages messages) { 39 Document parseHtml(contents, String sourcePath, Messages messages) {
43 var parser = new HtmlParser(contents, generateSpans: true, 40 var parser = new HtmlParser(contents, generateSpans: true,
44 sourceUrl: sourcePath); 41 sourceUrl: sourcePath);
45 var document = parser.parse(); 42 var document = parser.parse();
46 43
47 // Note: errors aren't fatal in HTML (unless strict mode is on). 44 // Note: errors aren't fatal in HTML (unless strict mode is on).
48 // So just print them as warnings. 45 // So just print them as warnings.
49 for (var e in parser.errors) { 46 for (var e in parser.errors) {
50 messages.warning(e.message, e.span); 47 messages.warning(e.message, e.span);
51 } 48 }
52 return document; 49 return document;
53 } 50 }
54 51
55 /** Compiles an application written with Dart web components. */ 52 /** Compiles an application written with Dart web components. */
56 class Compiler { 53 class Compiler {
57 final FileSystem fileSystem; 54 final FileSystem fileSystem;
58 final CompilerOptions options; 55 final CompilerOptions options;
59 final List<SourceFile> files = <SourceFile>[]; 56 final List<SourceFile> files = <SourceFile>[];
60 final List<OutputFile> output = <OutputFile>[];
61 57
62 String _mainPath; 58 String _mainPath;
63 String _resetCssFile; 59 String _resetCssFile;
64 StyleSheet _cssResetStyleSheet; 60 StyleSheet _cssResetStyleSheet;
65 PathMapper _pathMapper;
66 Messages _messages; 61 Messages _messages;
67 62
68 FutureGroup _tasks; 63 FutureGroup _tasks;
69 Set _processed; 64 Set _processed;
70 65
71 /** Information about source [files] given their href. */ 66 /** Information about source [files] given their href. */
72 final Map<String, FileInfo> info = new SplayTreeMap<String, FileInfo>(); 67 final Map<String, FileInfo> info = new SplayTreeMap<String, FileInfo>();
73 final _edits = new Map<DartCodeInfo, TextEditTransaction>(); 68 final _edits = new Map<DartCodeInfo, TextEditTransaction>();
74 69
75 final GlobalInfo global = new GlobalInfo(); 70 final GlobalInfo global = new GlobalInfo();
76 71
77 /** Creates a compiler with [options] using [fileSystem]. */ 72 /** Creates a compiler with [options] using [fileSystem]. */
78 Compiler(this.fileSystem, this.options, this._messages) { 73 Compiler(this.fileSystem, this.options, this._messages) {
79 _mainPath = options.inputFile; 74 _mainPath = options.inputFile;
80 var mainDir = path.dirname(_mainPath); 75 var mainDir = path.dirname(_mainPath);
81 var baseDir = options.baseDir != null ? options.baseDir : mainDir; 76 var baseDir = options.baseDir != null ? options.baseDir : mainDir;
82 var outputDir = options.outputDir != null ? options.outputDir : mainDir;
83 var packageRoot = options.packageRoot != null ? options.packageRoot
Jennifer Messerly 2013/08/28 22:25:45 we might want pkg root back now?
Siggi Cherem (dart-lang) 2013/08/28 23:17:06 Done.
84 : path.join(path.dirname(_mainPath), 'packages');
85 77
86 if (options.resetCssFile != null) { 78 if (options.resetCssFile != null) {
87 _resetCssFile = options.resetCssFile; 79 _resetCssFile = options.resetCssFile;
88 if (path.isRelative(_resetCssFile)) { 80 if (path.isRelative(_resetCssFile)) {
89 // If CSS reset file path is relative from our current path. 81 // If CSS reset file path is relative from our current path.
90 _resetCssFile = path.resolve(_resetCssFile); 82 _resetCssFile = path.resolve(_resetCssFile);
91 } 83 }
92 } 84 }
93 85
94 // Normalize paths - all should be relative or absolute paths. 86 // Normalize paths - all should be relative or absolute paths.
95 if (path.isAbsolute(_mainPath) || path.isAbsolute(baseDir) || 87 if (path.isAbsolute(_mainPath) || path.isAbsolute(baseDir)) {
96 path.isAbsolute(outputDir) || path.isAbsolute(packageRoot)) {
97 if (path.isRelative(_mainPath)) _mainPath = path.resolve(_mainPath); 88 if (path.isRelative(_mainPath)) _mainPath = path.resolve(_mainPath);
98 if (path.isRelative(baseDir)) baseDir = path.resolve(baseDir); 89 if (path.isRelative(baseDir)) baseDir = path.resolve(baseDir);
99 if (path.isRelative(outputDir)) outputDir = path.resolve(outputDir);
100 if (path.isRelative(packageRoot)) {
101 packageRoot = path.resolve(packageRoot);
102 }
103 } 90 }
104 _pathMapper = new PathMapper(
105 baseDir, outputDir, packageRoot, options.forceMangle,
106 options.rewriteUrls);
107 } 91 }
108 92
109 /** Compile the application starting from the given input file. */ 93 /** Compile the application starting from the given input file. */
110 Future run() { 94 Future run() {
111 if (path.basename(_mainPath).endsWith('.dart')) { 95 if (path.basename(_mainPath).endsWith('.dart')) {
112 _messages.error("Please provide an HTML file as your entry point.", 96 _messages.error("Please provide an HTML file as your entry point.",
113 null); 97 null);
114 return new Future.value(null); 98 return new Future.value(null);
115 } 99 }
116 return _parseAndDiscover(_mainPath).then((_) { 100 return _parseAndDiscover(_mainPath).then((_) {
117 _analyze(); 101 _analyze();
118 102
119 // Analyze all CSS files. 103 // Analyze all CSS files.
120 _time('Analyzed Style Sheets', '', () => 104 _time('Analyzed Style Sheets', '', () =>
121 analyzeCss(_pathMapper.packageRoot, files, info, 105 analyzeCss(files, info,
122 global.pseudoElements, _messages, 106 global.pseudoElements, _messages,
123 warningsAsErrors: options.warningsAsErrors)); 107 warningsAsErrors: options.warningsAsErrors));
124
125 // TODO(jmesserly): need to go through our errors, and figure out if some
126 // of them should be warnings instead.
127 if (_messages.hasErrors || options.analysisOnly) return;
128 _transformDart();
129 _emit();
130 }); 108 });
131 } 109 }
132 110
133 /** 111 /**
134 * Asynchronously parse [inputFile] and transitively discover web components 112 * Asynchronously parse [inputFile] and transitively discover web components
135 * to load and parse. Returns a future that completes when all files are 113 * to load and parse. Returns a future that completes when all files are
136 * processed. 114 * processed.
137 */ 115 */
138 Future _parseAndDiscover(String inputFile) { 116 Future _parseAndDiscover(String inputFile) {
139 _tasks = new FutureGroup(); 117 _tasks = new FutureGroup();
140 _processed = new Set(); 118 _processed = new Set();
141 _processed.add(inputFile); 119 _processed.add(inputFile);
142 _tasks.add(_parseHtmlFile(new UrlInfo(inputFile, inputFile, null))); 120 _tasks.add(_parseHtmlFile(new UrlInfo(inputFile, inputFile, null)));
143 return _tasks.future; 121 return _tasks.future;
144 } 122 }
145 123
146 void _processHtmlFile(UrlInfo inputUrl, SourceFile file) { 124 void _processHtmlFile(UrlInfo inputUrl, SourceFile file) {
147 if (file == null) return; 125 if (file == null) return;
148 126
149 bool isEntryPoint = _processed.length == 1; 127 bool isEntryPoint = _processed.length == 1;
150 128
151 files.add(file); 129 files.add(file);
152 130
153 var fileInfo = _time('Analyzed definitions', inputUrl.url, () { 131 var fileInfo = _time('Analyzed definitions', inputUrl.url, () {
154 return analyzeDefinitions(global, inputUrl, file.document, 132 return analyzeDefinitions(global, inputUrl, file.document,
155 _pathMapper.packageRoot, _messages, isEntryPoint: isEntryPoint); 133 _messages, isEntryPoint: isEntryPoint);
156 }); 134 });
157 info[inputUrl.resolvedPath] = fileInfo; 135 info[inputUrl.resolvedPath] = fileInfo;
158 136
159 if (isEntryPoint && _resetCssFile != null) { 137 if (isEntryPoint && _resetCssFile != null) {
160 _processed.add(_resetCssFile); 138 _processed.add(_resetCssFile);
161 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile, 139 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile,
162 null))); 140 null)));
163 } 141 }
164 142
165 _setOutputFilenames(fileInfo);
166 _processImports(fileInfo); 143 _processImports(fileInfo);
167 144
168 // Load component files referenced by [file]. 145 // Load component files referenced by [file].
169 for (var link in fileInfo.componentLinks) { 146 for (var link in fileInfo.componentLinks) {
170 _loadFile(link, _parseHtmlFile); 147 _loadFile(link, _parseHtmlFile);
171 } 148 }
172 149
173 // Load stylesheet files referenced by [file]. 150 // Load stylesheet files referenced by [file].
174 for (var link in fileInfo.styleSheetHrefs) { 151 for (var link in fileInfo.styleSheetHrefs) {
175 _loadFile(link, _parseCssFile); 152 _loadFile(link, _parseCssFile);
176 } 153 }
177 154
178 // Load .dart files being referenced in the page. 155 // Load .dart files being referenced in the page.
179 _loadFile(fileInfo.externalFile, _parseDartFile); 156 _loadFile(fileInfo.externalFile, _parseDartFile);
180 157
181 // Process any @imports inside of a <style> tag. 158 // Process any @imports inside of a <style> tag.
182 var urlInfos = findUrlsImported(fileInfo, fileInfo.inputUrl, 159 var urlInfos = findUrlsImported(fileInfo, fileInfo.inputUrl,
183 _pathMapper.packageRoot, file.document, _messages, options); 160 file.document, _messages, options);
184 for (var urlInfo in urlInfos) { 161 for (var urlInfo in urlInfos) {
185 _loadFile(urlInfo, _parseCssFile); 162 _loadFile(urlInfo, _parseCssFile);
186 } 163 }
187 164
188 // Load .dart files being referenced in components. 165 // Load .dart files being referenced in components.
189 for (var component in fileInfo.declaredComponents) { 166 for (var component in fileInfo.declaredComponents) {
190 if (component.externalFile != null) { 167 if (component.externalFile != null) {
191 _loadFile(component.externalFile, _parseDartFile); 168 _loadFile(component.externalFile, _parseDartFile);
192 } else if (component.userCode != null) { 169 } else if (component.userCode != null) {
193 _processImports(component); 170 _processImports(component);
194 } 171 }
195 172
196 // Process any @imports inside of the <style> tag in a component. 173 // Process any @imports inside of the <style> tag in a component.
197 var urlInfos = findUrlsImported(component, 174 var urlInfos = findUrlsImported(component,
198 component.declaringFile.inputUrl, _pathMapper.packageRoot, 175 component.declaringFile.inputUrl, component.element, _messages,
199 component.element, _messages, options); 176 options);
200 for (var urlInfo in urlInfos) { 177 for (var urlInfo in urlInfos) {
201 _loadFile(urlInfo, _parseCssFile); 178 _loadFile(urlInfo, _parseCssFile);
202 } 179 }
203 } 180 }
204 } 181 }
205 182
206 /** 183 /**
207 * Helper function to load [urlInfo] and parse it using [loadAndParse] if it 184 * Helper function to load [urlInfo] and parse it using [loadAndParse] if it
208 * hasn't been loaded before. 185 * hasn't been loaded before.
209 */ 186 */
210 void _loadFile(UrlInfo urlInfo, Future loadAndParse(UrlInfo inputUrl)) { 187 void _loadFile(UrlInfo urlInfo, Future loadAndParse(UrlInfo inputUrl)) {
211 if (urlInfo == null) return; 188 if (urlInfo == null) return;
212 var resolvedPath = urlInfo.resolvedPath; 189 var resolvedPath = urlInfo.resolvedPath;
213 if (!_processed.contains(resolvedPath)) { 190 if (!_processed.contains(resolvedPath)) {
214 _processed.add(resolvedPath); 191 _processed.add(resolvedPath);
215 _tasks.add(loadAndParse(urlInfo)); 192 _tasks.add(loadAndParse(urlInfo));
216 } 193 }
217 } 194 }
218 195
219 void _setOutputFilenames(FileInfo fileInfo) {
220 var filePath = fileInfo.dartCodeUrl.resolvedPath;
221 fileInfo.outputFilename = _pathMapper.mangle(path.basename(filePath),
222 '.dart', path.extension(filePath) == '.html');
223 for (var component in fileInfo.declaredComponents) {
224 var externalFile = component.externalFile;
225 var name = null;
226 if (externalFile != null) {
227 name = _pathMapper.mangle(
228 path.basename(externalFile.resolvedPath), '.dart');
229 } else {
230 var declaringFile = component.declaringFile;
231 var prefix = path.basename(declaringFile.inputUrl.resolvedPath);
232 if (declaringFile.declaredComponents.length == 1
233 && !declaringFile.codeAttached && !declaringFile.isEntryPoint) {
234 name = _pathMapper.mangle(prefix, '.dart', true);
235 } else {
236 var componentName = component.tagName.replaceAll('-', '_');
237 name = _pathMapper.mangle('${prefix}_$componentName', '.dart', true);
238 }
239 }
240 component.outputFilename = name;
241 }
242 }
243
244 /** Parse an HTML file. */ 196 /** Parse an HTML file. */
245 Future _parseHtmlFile(UrlInfo inputUrl) { 197 Future _parseHtmlFile(UrlInfo inputUrl) {
246 if (!_pathMapper.checkInputPath(inputUrl, _messages)) {
247 return new Future<SourceFile>.value(null);
248 }
249 var filePath = inputUrl.resolvedPath; 198 var filePath = inputUrl.resolvedPath;
250 return fileSystem.readTextOrBytes(filePath) 199 return fileSystem.readTextOrBytes(filePath)
251 .catchError((e) => _readError(e, inputUrl)) 200 .catchError((e) => _readError(e, inputUrl))
252 .then((source) { 201 .then((source) {
253 if (source == null) return; 202 if (source == null) return;
254 var file = new SourceFile(filePath); 203 var file = new SourceFile(filePath);
255 file.document = _time('Parsed', filePath, 204 file.document = _time('Parsed', filePath,
256 () => parseHtml(source, filePath, _messages)); 205 () => parseHtml(source, filePath, _messages));
257 _processHtmlFile(inputUrl, file); 206 _processHtmlFile(inputUrl, file);
258 }); 207 });
259 } 208 }
260 209
261 /** Parse a Dart file. */ 210 /** Parse a Dart file. */
262 Future _parseDartFile(UrlInfo inputUrl) { 211 Future _parseDartFile(UrlInfo inputUrl) {
263 if (!_pathMapper.checkInputPath(inputUrl, _messages)) {
264 return new Future<SourceFile>.value(null);
265 }
266 var filePath = inputUrl.resolvedPath; 212 var filePath = inputUrl.resolvedPath;
267 return fileSystem.readText(filePath) 213 return fileSystem.readText(filePath)
268 .catchError((e) => _readError(e, inputUrl)) 214 .catchError((e) => _readError(e, inputUrl))
269 .then((code) { 215 .then((code) {
270 if (code == null) return; 216 if (code == null) return;
271 var file = new SourceFile(filePath, type: SourceFile.DART); 217 var file = new SourceFile(filePath, type: SourceFile.DART);
272 file.code = code; 218 file.code = code;
273 _processDartFile(inputUrl, file); 219 _processDartFile(inputUrl, file);
274 }); 220 });
275 } 221 }
276 222
277 /** Parse a stylesheet file. */ 223 /** Parse a stylesheet file. */
278 Future _parseCssFile(UrlInfo inputUrl) { 224 Future _parseCssFile(UrlInfo inputUrl) {
279 if (!options.emulateScopedCss || 225 if (!options.emulateScopedCss) {
280 !_pathMapper.checkInputPath(inputUrl, _messages)) {
281 return new Future<SourceFile>.value(null); 226 return new Future<SourceFile>.value(null);
282 } 227 }
283 var filePath = inputUrl.resolvedPath; 228 var filePath = inputUrl.resolvedPath;
284 return fileSystem.readText(filePath) 229 return fileSystem.readText(filePath)
285 .catchError((e) => _readError(e, inputUrl, isWarning: true)) 230 .catchError((e) => _readError(e, inputUrl, isWarning: true))
286 .then((code) { 231 .then((code) {
287 if (code == null) return; 232 if (code == null) return;
288 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET); 233 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET);
289 file.code = code; 234 file.code = code;
290 _processCssFile(inputUrl, file); 235 _processCssFile(inputUrl, file);
(...skipping 16 matching lines...) Expand all
307 252
308 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) { 253 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) {
309 if (dartFile == null) return; 254 if (dartFile == null) return;
310 255
311 files.add(dartFile); 256 files.add(dartFile);
312 257
313 var resolvedPath = inputUrl.resolvedPath; 258 var resolvedPath = inputUrl.resolvedPath;
314 var fileInfo = new FileInfo(inputUrl); 259 var fileInfo = new FileInfo(inputUrl);
315 info[resolvedPath] = fileInfo; 260 info[resolvedPath] = fileInfo;
316 fileInfo.inlinedCode = parseDartCode(resolvedPath, dartFile.code); 261 fileInfo.inlinedCode = parseDartCode(resolvedPath, dartFile.code);
317 fileInfo.outputFilename =
318 _pathMapper.mangle(path.basename(resolvedPath), '.dart', false);
319
320 _processImports(fileInfo); 262 _processImports(fileInfo);
321 } 263 }
322 264
323 void _processImports(LibraryInfo library) { 265 void _processImports(LibraryInfo library) {
324 if (library.userCode == null) return; 266 if (library.userCode == null) return;
325 267
326 for (var directive in library.userCode.directives) { 268 for (var directive in library.userCode.directives) {
327 _loadFile(_getDirectiveUrlInfo(library, directive), _parseDartFile); 269 _loadFile(_getDirectiveUrlInfo(library, directive), _parseDartFile);
328 } 270 }
329 } 271 }
(...skipping 12 matching lines...) Expand all
342 } else if (styleSheet != null) { 284 } else if (styleSheet != null) {
343 _resolveStyleSheetImports(inputUrl, cssFile.path, styleSheet); 285 _resolveStyleSheetImports(inputUrl, cssFile.path, styleSheet);
344 fileInfo.styleSheets.add(styleSheet); 286 fileInfo.styleSheets.add(styleSheet);
345 } 287 }
346 } 288 }
347 289
348 /** Load and parse all style sheets referenced with an @imports. */ 290 /** Load and parse all style sheets referenced with an @imports. */
349 void _resolveStyleSheetImports(UrlInfo inputUrl, String processingFile, 291 void _resolveStyleSheetImports(UrlInfo inputUrl, String processingFile,
350 StyleSheet styleSheet) { 292 StyleSheet styleSheet) {
351 var urlInfos = _time('CSS imports', processingFile, () => 293 var urlInfos = _time('CSS imports', processingFile, () =>
352 findImportsInStyleSheet(styleSheet, _pathMapper.packageRoot, inputUrl, 294 findImportsInStyleSheet(styleSheet, inputUrl, _messages));
353 _messages));
354 295
355 for (var urlInfo in urlInfos) { 296 for (var urlInfo in urlInfos) {
356 if (urlInfo == null) break; 297 if (urlInfo == null) break;
357 // Load any @imported stylesheet files referenced in this style sheet. 298 // Load any @imported stylesheet files referenced in this style sheet.
358 _loadFile(urlInfo, _parseCssFile); 299 _loadFile(urlInfo, _parseCssFile);
359 } 300 }
360 } 301 }
361 302
362 String _directiveUri(Directive directive) { 303 String _directiveUri(Directive directive) {
363 var uriDirective = (directive as UriBasedDirective).uri; 304 var uriDirective = (directive as UriBasedDirective).uri;
364 return (uriDirective as dynamic).value; 305 return (uriDirective as dynamic).value;
365 } 306 }
366 307
367 UrlInfo _getDirectiveUrlInfo(LibraryInfo library, Directive directive) { 308 UrlInfo _getDirectiveUrlInfo(LibraryInfo library, Directive directive) {
368 var uri = _directiveUri(directive); 309 var uri = _directiveUri(directive);
369 if (uri.startsWith('dart:')) return null; 310 if (uri.startsWith('dart:')) return null;
370 if (uri.startsWith('package:') && uri.startsWith('package:polymer/')) { 311 if (uri.startsWith('package:') && uri.startsWith('package:polymer/')) {
371 // Don't process our own package -- we'll implement @observable manually. 312 // Don't process our own package -- we'll implement @observable manually.
372 return null; 313 return null;
373 } 314 }
374 315
375 var span = library.userCode.sourceFile.span( 316 var span = library.userCode.sourceFile.span(
376 directive.offset, directive.end); 317 directive.offset, directive.end);
377 return UrlInfo.resolve(uri, library.dartCodeUrl, span, 318 return UrlInfo.resolve(uri, library.dartCodeUrl, span, _messages);
378 _pathMapper.packageRoot, _messages);
379 } 319 }
380 320
381 /** 321 /**
382 * Transform Dart source code.
383 * Currently, the only transformation is [transformObservables].
384 * Calls _emitModifiedDartFiles to write the transformed files.
385 */
386 void _transformDart() {
387 var libraries = _findAllDartLibraries();
388
389 var transformed = [];
390 for (var lib in libraries) {
391 var userCode = lib.userCode;
392 var transaction = transformObservables(userCode.compilationUnit,
393 userCode.sourceFile, userCode.code, _messages);
394 if (transaction != null) {
395 _edits[lib.userCode] = transaction;
396 if (transaction.hasEdits) {
397 transformed.add(lib);
398 } else if (lib.htmlFile != null) {
399 // All web components will be transformed too. Track that.
400 transformed.add(lib);
401 }
402 }
403 }
404
405 _findModifiedDartFiles(libraries, transformed);
406
407 libraries.forEach(_fixImports);
408
409 _emitModifiedDartFiles(libraries);
410 }
411
412 /**
413 * Finds all Dart code libraries. 322 * Finds all Dart code libraries.
414 * Each library will have [LibraryInfo.inlinedCode] that is non-null. 323 * Each library will have [LibraryInfo.inlinedCode] that is non-null.
415 * Also each inlinedCode will be unique. 324 * Also each inlinedCode will be unique.
416 */ 325 */
417 List<LibraryInfo> _findAllDartLibraries() { 326 List<LibraryInfo> _findAllDartLibraries() {
418 var libs = <LibraryInfo>[]; 327 var libs = <LibraryInfo>[];
419 void _addLibrary(LibraryInfo lib) { 328 void _addLibrary(LibraryInfo lib) {
420 if (lib.inlinedCode != null) libs.add(lib); 329 if (lib.inlinedCode != null) libs.add(lib);
421 } 330 }
422 331
(...skipping 15 matching lines...) Expand all
438 throw new StateError('internal error: ' 347 throw new StateError('internal error: '
439 'duplicate user code for ${lib.dartCodeUrl.resolvedPath}.' 348 'duplicate user code for ${lib.dartCodeUrl.resolvedPath}.'
440 ' Files were: $files'); 349 ' Files were: $files');
441 } 350 }
442 seen.add(lib.inlinedCode); 351 seen.add(lib.inlinedCode);
443 } 352 }
444 return true; 353 return true;
445 } 354 }
446 355
447 /** 356 /**
448 * Queue modified Dart files to be written.
449 * This will not write files that are handled by [WebComponentEmitter] and
450 * [EntryPointEmitter].
451 */
452 void _emitModifiedDartFiles(List<LibraryInfo> libraries) {
453 for (var lib in libraries) {
454 // Components will get emitted by WebComponentEmitter, and the
455 // entry point will get emitted by MainPageEmitter.
456 // So we only need to worry about other .dart files.
457 if (lib.modified && lib is FileInfo &&
458 lib.htmlFile == null && !lib.isEntryPoint) {
459 var transaction = _edits[lib.userCode];
460
461 // Save imports that were modified by _fixImports.
462 for (var d in lib.userCode.directives) {
463 transaction.edit(d.offset, d.end, d.toString());
464 }
465
466 if (!lib.userCode.isPart) {
467 var pos = lib.userCode.firstPartOffset;
468 // Note: we use a different prefix than "autogenerated" to make
469 // ChangeRecord unambiguous. Otherwise it would be imported by this
470 // and polymer, resulting in a collision.
471 // TODO(jmesserly): only generate this for libraries that need it.
472 transaction.edit(pos, pos, "\nimport "
473 "'package:observe/observe.dart' as __observe;\n");
474 }
475 _emitFileAndSourceMaps(lib, transaction.commit(), lib.dartCodeUrl);
476 }
477 }
478 }
479
480 /**
481 * This method computes which Dart files have been modified, starting 357 * This method computes which Dart files have been modified, starting
482 * from [transformed] and marking recursively through all files that import 358 * from [transformed] and marking recursively through all files that import
483 * the modified files. 359 * the modified files.
484 */ 360 */
485 void _findModifiedDartFiles(List<LibraryInfo> libraries, 361 void _findModifiedDartFiles(List<LibraryInfo> libraries,
486 List<FileInfo> transformed) { 362 List<FileInfo> transformed) {
487 363
488 if (transformed.length == 0) return; 364 if (transformed.length == 0) return;
489 365
490 // Compute files that reference each file, then use this information to 366 // Compute files that reference each file, then use this information to
(...skipping 18 matching lines...) Expand all
509 library.referencedBy.forEach(setModified); 385 library.referencedBy.forEach(setModified);
510 } 386 }
511 transformed.forEach(setModified); 387 transformed.forEach(setModified);
512 388
513 for (var lib in libraries) { 389 for (var lib in libraries) {
514 // We don't need this anymore, so free it. 390 // We don't need this anymore, so free it.
515 lib.referencedBy = null; 391 lib.referencedBy = null;
516 } 392 }
517 } 393 }
518 394
519 void _fixImports(LibraryInfo library) {
520 // Fix imports. Modified files must use the generated path, otherwise
521 // we need to make the path relative to the input.
522 for (var directive in library.userCode.directives) {
523 var importPath = _getDirectiveUrlInfo(library, directive);
524 if (importPath == null) continue;
525 var importInfo = info[importPath.resolvedPath];
526 if (importInfo == null) continue;
527
528 String newUri = null;
529 if (importInfo.modified) {
530 // Use the generated URI for this file.
531 newUri = _pathMapper.importUrlFor(library, importInfo);
532 } else if (options.rewriteUrls) {
533 // Get the relative path to the input file.
534 newUri = _pathMapper.transformUrl(
535 library.dartCodeUrl.resolvedPath, directive.uri.value);
536 }
537 if (newUri != null) {
538 directive.uri = createStringLiteral(newUri);
539 }
540 }
541 }
542
543 /** Run the analyzer on every input html file. */ 395 /** Run the analyzer on every input html file. */
544 void _analyze() { 396 void _analyze() {
545 var uniqueIds = new IntIterator(); 397 var uniqueIds = new IntIterator();
546 for (var file in files) { 398 for (var file in files) {
547 if (file.isHtml) { 399 if (file.isHtml) {
548 _time('Analyzed contents', file.path, () => 400 _time('Analyzed contents', file.path, () =>
549 analyzeFile(file, info, uniqueIds, global, _messages, 401 analyzeFile(file, info, uniqueIds, global, _messages,
550 options.emulateScopedCss)); 402 options.emulateScopedCss));
551 } 403 }
552 } 404 }
553 } 405 }
554 406
555 /** Emit the generated code corresponding to each input file. */
556 void _emit() {
557 for (var file in files) {
558 if (file.isDart || file.isStyleSheet) continue;
559 _time('Codegen', file.path, () {
560 var fileInfo = info[file.path];
561 _emitComponents(fileInfo);
562 });
563 }
564
565 var entryPoint = files[0];
566 assert(info[entryPoint.path].isEntryPoint);
567 _emitMainDart(entryPoint);
568 _emitMainHtml(entryPoint);
569
570 assert(_unqiueOutputs());
571 }
572
573 bool _unqiueOutputs() {
574 var seen = new Set();
575 for (var file in output) {
576 if (seen.contains(file.path)) {
577 throw new StateError('internal error: '
578 'duplicate output file ${file.path}. Files were: $output');
579 }
580 seen.add(file.path);
581 }
582 return true;
583 }
584
585 /** Emit the main .dart file. */
586 void _emitMainDart(SourceFile file) {
587 var fileInfo = info[file.path];
588
589 var codeInfo = fileInfo.userCode;
590 if (codeInfo != null) {
591 var printer = new NestedPrinter(0);
592 if (codeInfo.libraryName == null) {
593 printer.addLine('library ${fileInfo.libraryName};');
594 }
595 printer.add(codeInfo.code);
596 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.dartCodeUrl);
597 }
598 }
599
600 // TODO(jmesserly): refactor this out of Compiler.
601 /** Generate an html file with the (trimmed down) main html page. */
602 void _emitMainHtml(SourceFile file) {
603 var fileInfo = info[file.path];
604
605 var bootstrapName = '${path.basename(file.path)}_bootstrap.dart';
606 var bootstrapPath = path.join(path.dirname(file.path), bootstrapName);
607 var bootstrapOutPath = _pathMapper.outputPath(bootstrapPath, '');
608 var bootstrapOutName = path.basename(bootstrapOutPath);
609 var bootstrapInfo = new FileInfo(new UrlInfo('', bootstrapPath, null));
610 var printer = generateBootstrapCode(bootstrapInfo, fileInfo, global,
611 _pathMapper, options);
612 printer.build(bootstrapOutPath);
613 output.add(new OutputFile(
614 bootstrapOutPath, printer.text, source: file.path));
615
616 var document = file.document;
617 var hasCss = _emitAllCss();
618 transformMainHtml(document, fileInfo, _pathMapper, hasCss,
619 options.rewriteUrls, _messages, global, bootstrapOutName);
620 output.add(new OutputFile(_pathMapper.outputPath(file.path, '.html'),
621 document.outerHtml, source: file.path));
622 }
623
624 // TODO(jmesserly): refactor this and other CSS related transforms out of 407 // TODO(jmesserly): refactor this and other CSS related transforms out of
625 // Compiler. 408 // Compiler.
626 /** 409 /**
627 * Generate an CSS file for all style sheets (main and components). 410 * Generate an CSS file for all style sheets (main and components).
628 * Returns true if a file was generated, otherwise false. 411 * Returns true if a file was generated, otherwise false.
629 */ 412 */
630 bool _emitAllCss() { 413 bool _emitAllCss() {
Siggi Cherem (dart-lang) 2013/08/27 23:30:14 On a future CL I plan to go deeper in removing som
631 if (!options.emulateScopedCss) return false; 414 if (!options.emulateScopedCss) return false;
632 415
633 var buff = new StringBuffer(); 416 var buff = new StringBuffer();
634 417
635 // Emit all linked style sheet files first. 418 // Emit all linked style sheet files first.
636 for (var file in files) { 419 for (var file in files) {
637 var css = new StringBuffer(); 420 var css = new StringBuffer();
638 var fileInfo = info[file.path]; 421 var fileInfo = info[file.path];
639 if (file.isStyleSheet) { 422 if (file.isStyleSheet) {
640 for (var styleSheet in fileInfo.styleSheets) { 423 for (var styleSheet in fileInfo.styleSheets) {
641 // Translate any URIs in CSS. 424 // Translate any URIs in CSS.
642 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath, 425 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath,
643 options.rewriteUrls, styleSheet); 426 options.rewriteUrls, styleSheet);
644 css.write( 427 css.write(
645 '/* Auto-generated from style sheet href = ${file.path} */\n' 428 '/* Auto-generated from style sheet href = ${file.path} */\n'
646 '/* DO NOT EDIT. */\n\n'); 429 '/* DO NOT EDIT. */\n\n');
647 css.write(emitStyleSheet(styleSheet, fileInfo)); 430 css.write(emitStyleSheet(styleSheet, fileInfo));
648 css.write('\n\n'); 431 css.write('\n\n');
649 } 432 }
650
651 // Emit the linked style sheet in the output directory.
652 if (fileInfo.inputUrl.url != _resetCssFile) {
653 var outCss = _pathMapper.outputPath(fileInfo.inputUrl.resolvedPath,
654 '');
655 output.add(new OutputFile(outCss, css.toString()));
656 }
657 } 433 }
658 } 434 }
659 435
660 // Emit all CSS for each component (style scoped). 436 // Emit all CSS for each component (style scoped).
661 for (var file in files) { 437 for (var file in files) {
662 if (file.isHtml) { 438 if (file.isHtml) {
663 var fileInfo = info[file.path]; 439 var fileInfo = info[file.path];
664 for (var component in fileInfo.declaredComponents) { 440 for (var component in fileInfo.declaredComponents) {
665 for (var styleSheet in component.styleSheets) { 441 for (var styleSheet in component.styleSheets) {
666 // Translate any URIs in CSS. 442 // Translate any URIs in CSS.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 } 481 }
706 } 482 }
707 483
708 if (buff.isEmpty) return false; 484 if (buff.isEmpty) return false;
709 485
710 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true); 486 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true);
711 output.add(new OutputFile(cssPath, buff.toString())); 487 output.add(new OutputFile(cssPath, buff.toString()));
712 return true; 488 return true;
713 } 489 }
714 490
715 /** Emits the Dart code for all components in [fileInfo]. */
716 void _emitComponents(FileInfo fileInfo) {
717 for (var component in fileInfo.declaredComponents) {
718 // TODO(terry): Handle more than one stylesheet per component
719 if (component.styleSheets.length > 1 && options.emulateScopedCss) {
720 var span = component.externalFile != null
721 ? component.externalFile.sourceSpan : null;
722 _messages.warning(
723 'Component has more than one stylesheet - first stylesheet used.',
724 span);
725 }
726 var printer = emitPolymerElement(
727 component, _pathMapper, _edits[component.userCode], options);
728 _emitFileAndSourceMaps(component, printer, component.externalFile);
729 }
730 }
731
732 /**
733 * Emits a file that was created using [NestedPrinter] and it's corresponding
734 * source map file.
735 */
736 void _emitFileAndSourceMaps(
737 LibraryInfo lib, NestedPrinter printer, UrlInfo dartCodeUrl) {
738 // Bail if we had an error generating the code for the file.
739 if (printer == null) return;
740
741 var libPath = _pathMapper.outputLibraryPath(lib);
742 var dir = path.dirname(libPath);
743 var filename = path.basename(libPath);
744 printer.add('\n//# sourceMappingURL=$filename.map');
745 printer.build(libPath);
746 var sourcePath = dartCodeUrl != null ? dartCodeUrl.resolvedPath : null;
747 output.add(new OutputFile(libPath, printer.text, source: sourcePath));
748 // Fix-up the paths in the source map file
749 var sourceMap = json.parse(printer.map);
750 var urls = sourceMap['sources'];
751 for (int i = 0; i < urls.length; i++) {
752 urls[i] = path.relative(urls[i], from: dir);
753 }
754 output.add(new OutputFile(path.join(dir, '$filename.map'),
755 json.stringify(sourceMap)));
756 }
757
758 _time(String logMessage, String filePath, callback(), 491 _time(String logMessage, String filePath, callback(),
759 {bool printTime: false}) { 492 {bool printTime: false}) {
760 var message = new StringBuffer(); 493 var message = new StringBuffer();
761 message.write(logMessage); 494 message.write(logMessage);
762 var filename = path.basename(filePath); 495 var filename = path.basename(filePath);
763 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) { 496 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) {
764 message.write(' '); 497 message.write(' ');
765 } 498 }
766 message.write(filename); 499 message.write(filename);
767 return time(message.toString(), callback, 500 return time(message.toString(), callback,
768 printTime: options.verbose || printTime); 501 printTime: options.verbose || printTime);
769 } 502 }
770 } 503 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698