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

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
« no previous file with comments | « pkg/polymer/lib/safe_html.dart ('k') | pkg/polymer/lib/src/compiler_options.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
59 String _packageRoot;
63 String _resetCssFile; 60 String _resetCssFile;
64 StyleSheet _cssResetStyleSheet; 61 StyleSheet _cssResetStyleSheet;
65 PathMapper _pathMapper;
66 Messages _messages; 62 Messages _messages;
67 63
68 FutureGroup _tasks; 64 FutureGroup _tasks;
69 Set _processed; 65 Set _processed;
70 66
71 /** Information about source [files] given their href. */ 67 /** Information about source [files] given their href. */
72 final Map<String, FileInfo> info = new SplayTreeMap<String, FileInfo>(); 68 final Map<String, FileInfo> info = new SplayTreeMap<String, FileInfo>();
73 final _edits = new Map<DartCodeInfo, TextEditTransaction>(); 69 final _edits = new Map<DartCodeInfo, TextEditTransaction>();
74 70
75 final GlobalInfo global = new GlobalInfo(); 71 final GlobalInfo global = new GlobalInfo();
76 72
77 /** Creates a compiler with [options] using [fileSystem]. */ 73 /** Creates a compiler with [options] using [fileSystem]. */
78 Compiler(this.fileSystem, this.options, this._messages) { 74 Compiler(this.fileSystem, this.options, this._messages) {
79 _mainPath = options.inputFile; 75 _mainPath = options.inputFile;
80 var mainDir = path.dirname(_mainPath); 76 var mainDir = path.dirname(_mainPath);
81 var baseDir = options.baseDir != null ? options.baseDir : mainDir; 77 var baseDir = options.baseDir != null ? options.baseDir : mainDir;
82 var outputDir = options.outputDir != null ? options.outputDir : mainDir; 78 _packageRoot = options.packageRoot != null ? options.packageRoot
83 var packageRoot = options.packageRoot != null ? options.packageRoot
84 : path.join(path.dirname(_mainPath), 'packages'); 79 : path.join(path.dirname(_mainPath), 'packages');
85 80
86 if (options.resetCssFile != null) { 81 if (options.resetCssFile != null) {
87 _resetCssFile = options.resetCssFile; 82 _resetCssFile = options.resetCssFile;
88 if (path.isRelative(_resetCssFile)) { 83 if (path.isRelative(_resetCssFile)) {
89 // If CSS reset file path is relative from our current path. 84 // If CSS reset file path is relative from our current path.
90 _resetCssFile = path.resolve(_resetCssFile); 85 _resetCssFile = path.resolve(_resetCssFile);
91 } 86 }
92 } 87 }
93 88
94 // Normalize paths - all should be relative or absolute paths. 89 // Normalize paths - all should be relative or absolute paths.
95 if (path.isAbsolute(_mainPath) || path.isAbsolute(baseDir) || 90 if (path.isAbsolute(_mainPath) || path.isAbsolute(baseDir)
96 path.isAbsolute(outputDir) || path.isAbsolute(packageRoot)) { 91 || path.isAbsolute(_packageRoot)) {
97 if (path.isRelative(_mainPath)) _mainPath = path.resolve(_mainPath); 92 if (path.isRelative(_mainPath)) _mainPath = path.resolve(_mainPath);
98 if (path.isRelative(baseDir)) baseDir = path.resolve(baseDir); 93 if (path.isRelative(baseDir)) baseDir = path.resolve(baseDir);
99 if (path.isRelative(outputDir)) outputDir = path.resolve(outputDir); 94 if (path.isRelative(_packageRoot)) {
100 if (path.isRelative(packageRoot)) { 95 _packageRoot = path.resolve(_packageRoot);
101 packageRoot = path.resolve(packageRoot);
102 } 96 }
103 } 97 }
104 _pathMapper = new PathMapper(
105 baseDir, outputDir, packageRoot, options.forceMangle,
106 options.rewriteUrls);
107 } 98 }
108 99
109 /** Compile the application starting from the given input file. */ 100 /** Compile the application starting from the given input file. */
110 Future run() { 101 Future run() {
111 if (path.basename(_mainPath).endsWith('.dart')) { 102 if (path.basename(_mainPath).endsWith('.dart')) {
112 _messages.error("Please provide an HTML file as your entry point.", 103 _messages.error("Please provide an HTML file as your entry point.",
113 null); 104 null);
114 return new Future.value(null); 105 return new Future.value(null);
115 } 106 }
116 return _parseAndDiscover(_mainPath).then((_) { 107 return _parseAndDiscover(_mainPath).then((_) {
117 _analyze(); 108 _analyze();
118 109
119 // Analyze all CSS files. 110 // Analyze all CSS files.
120 _time('Analyzed Style Sheets', '', () => 111 _time('Analyzed Style Sheets', '', () =>
121 analyzeCss(_pathMapper.packageRoot, files, info, 112 analyzeCss(_packageRoot, files, info,
122 global.pseudoElements, _messages, 113 global.pseudoElements, _messages,
123 warningsAsErrors: options.warningsAsErrors)); 114 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 }); 115 });
131 } 116 }
132 117
133 /** 118 /**
134 * Asynchronously parse [inputFile] and transitively discover web components 119 * Asynchronously parse [inputFile] and transitively discover web components
135 * to load and parse. Returns a future that completes when all files are 120 * to load and parse. Returns a future that completes when all files are
136 * processed. 121 * processed.
137 */ 122 */
138 Future _parseAndDiscover(String inputFile) { 123 Future _parseAndDiscover(String inputFile) {
139 _tasks = new FutureGroup(); 124 _tasks = new FutureGroup();
140 _processed = new Set(); 125 _processed = new Set();
141 _processed.add(inputFile); 126 _processed.add(inputFile);
142 _tasks.add(_parseHtmlFile(new UrlInfo(inputFile, inputFile, null))); 127 _tasks.add(_parseHtmlFile(new UrlInfo(inputFile, inputFile, null)));
143 return _tasks.future; 128 return _tasks.future;
144 } 129 }
145 130
146 void _processHtmlFile(UrlInfo inputUrl, SourceFile file) { 131 void _processHtmlFile(UrlInfo inputUrl, SourceFile file) {
147 if (file == null) return; 132 if (file == null) return;
148 133
149 bool isEntryPoint = _processed.length == 1; 134 bool isEntryPoint = _processed.length == 1;
150 135
151 files.add(file); 136 files.add(file);
152 137
153 var fileInfo = _time('Analyzed definitions', inputUrl.url, () { 138 var fileInfo = _time('Analyzed definitions', inputUrl.url, () {
154 return analyzeDefinitions(global, inputUrl, file.document, 139 return analyzeDefinitions(global, inputUrl, file.document, _packageRoot,
155 _pathMapper.packageRoot, _messages, isEntryPoint: isEntryPoint); 140 _messages, isEntryPoint: isEntryPoint);
156 }); 141 });
157 info[inputUrl.resolvedPath] = fileInfo; 142 info[inputUrl.resolvedPath] = fileInfo;
158 143
159 if (isEntryPoint && _resetCssFile != null) { 144 if (isEntryPoint && _resetCssFile != null) {
160 _processed.add(_resetCssFile); 145 _processed.add(_resetCssFile);
161 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile, 146 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile,
162 null))); 147 null)));
163 } 148 }
164 149
165 _setOutputFilenames(fileInfo);
166 _processImports(fileInfo); 150 _processImports(fileInfo);
167 151
168 // Load component files referenced by [file]. 152 // Load component files referenced by [file].
169 for (var link in fileInfo.componentLinks) { 153 for (var link in fileInfo.componentLinks) {
170 _loadFile(link, _parseHtmlFile); 154 _loadFile(link, _parseHtmlFile);
171 } 155 }
172 156
173 // Load stylesheet files referenced by [file]. 157 // Load stylesheet files referenced by [file].
174 for (var link in fileInfo.styleSheetHrefs) { 158 for (var link in fileInfo.styleSheetHrefs) {
175 _loadFile(link, _parseCssFile); 159 _loadFile(link, _parseCssFile);
176 } 160 }
177 161
178 // Load .dart files being referenced in the page. 162 // Load .dart files being referenced in the page.
179 _loadFile(fileInfo.externalFile, _parseDartFile); 163 _loadFile(fileInfo.externalFile, _parseDartFile);
180 164
181 // Process any @imports inside of a <style> tag. 165 // Process any @imports inside of a <style> tag.
182 var urlInfos = findUrlsImported(fileInfo, fileInfo.inputUrl, 166 var urlInfos = findUrlsImported(fileInfo, fileInfo.inputUrl, _packageRoot,
183 _pathMapper.packageRoot, file.document, _messages, options); 167 file.document, _messages, options);
184 for (var urlInfo in urlInfos) { 168 for (var urlInfo in urlInfos) {
185 _loadFile(urlInfo, _parseCssFile); 169 _loadFile(urlInfo, _parseCssFile);
186 } 170 }
187 171
188 // Load .dart files being referenced in components. 172 // Load .dart files being referenced in components.
189 for (var component in fileInfo.declaredComponents) { 173 for (var component in fileInfo.declaredComponents) {
190 if (component.externalFile != null) { 174 if (component.externalFile != null) {
191 _loadFile(component.externalFile, _parseDartFile); 175 _loadFile(component.externalFile, _parseDartFile);
192 } else if (component.userCode != null) { 176 } else if (component.userCode != null) {
193 _processImports(component); 177 _processImports(component);
194 } 178 }
195 179
196 // Process any @imports inside of the <style> tag in a component. 180 // Process any @imports inside of the <style> tag in a component.
197 var urlInfos = findUrlsImported(component, 181 var urlInfos = findUrlsImported(component,
198 component.declaringFile.inputUrl, _pathMapper.packageRoot, 182 component.declaringFile.inputUrl, _packageRoot, component.element,
199 component.element, _messages, options); 183 _messages, options);
200 for (var urlInfo in urlInfos) { 184 for (var urlInfo in urlInfos) {
201 _loadFile(urlInfo, _parseCssFile); 185 _loadFile(urlInfo, _parseCssFile);
202 } 186 }
203 } 187 }
204 } 188 }
205 189
206 /** 190 /**
207 * Helper function to load [urlInfo] and parse it using [loadAndParse] if it 191 * Helper function to load [urlInfo] and parse it using [loadAndParse] if it
208 * hasn't been loaded before. 192 * hasn't been loaded before.
209 */ 193 */
210 void _loadFile(UrlInfo urlInfo, Future loadAndParse(UrlInfo inputUrl)) { 194 void _loadFile(UrlInfo urlInfo, Future loadAndParse(UrlInfo inputUrl)) {
211 if (urlInfo == null) return; 195 if (urlInfo == null) return;
212 var resolvedPath = urlInfo.resolvedPath; 196 var resolvedPath = urlInfo.resolvedPath;
213 if (!_processed.contains(resolvedPath)) { 197 if (!_processed.contains(resolvedPath)) {
214 _processed.add(resolvedPath); 198 _processed.add(resolvedPath);
215 _tasks.add(loadAndParse(urlInfo)); 199 _tasks.add(loadAndParse(urlInfo));
216 } 200 }
217 } 201 }
218 202
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. */ 203 /** Parse an HTML file. */
245 Future _parseHtmlFile(UrlInfo inputUrl) { 204 Future _parseHtmlFile(UrlInfo inputUrl) {
246 if (!_pathMapper.checkInputPath(inputUrl, _messages)) {
247 return new Future<SourceFile>.value(null);
248 }
249 var filePath = inputUrl.resolvedPath; 205 var filePath = inputUrl.resolvedPath;
250 return fileSystem.readTextOrBytes(filePath) 206 return fileSystem.readTextOrBytes(filePath)
251 .catchError((e) => _readError(e, inputUrl)) 207 .catchError((e) => _readError(e, inputUrl))
252 .then((source) { 208 .then((source) {
253 if (source == null) return; 209 if (source == null) return;
254 var file = new SourceFile(filePath); 210 var file = new SourceFile(filePath);
255 file.document = _time('Parsed', filePath, 211 file.document = _time('Parsed', filePath,
256 () => parseHtml(source, filePath, _messages)); 212 () => parseHtml(source, filePath, _messages));
257 _processHtmlFile(inputUrl, file); 213 _processHtmlFile(inputUrl, file);
258 }); 214 });
259 } 215 }
260 216
261 /** Parse a Dart file. */ 217 /** Parse a Dart file. */
262 Future _parseDartFile(UrlInfo inputUrl) { 218 Future _parseDartFile(UrlInfo inputUrl) {
263 if (!_pathMapper.checkInputPath(inputUrl, _messages)) {
264 return new Future<SourceFile>.value(null);
265 }
266 var filePath = inputUrl.resolvedPath; 219 var filePath = inputUrl.resolvedPath;
267 return fileSystem.readText(filePath) 220 return fileSystem.readText(filePath)
268 .catchError((e) => _readError(e, inputUrl)) 221 .catchError((e) => _readError(e, inputUrl))
269 .then((code) { 222 .then((code) {
270 if (code == null) return; 223 if (code == null) return;
271 var file = new SourceFile(filePath, type: SourceFile.DART); 224 var file = new SourceFile(filePath, type: SourceFile.DART);
272 file.code = code; 225 file.code = code;
273 _processDartFile(inputUrl, file); 226 _processDartFile(inputUrl, file);
274 }); 227 });
275 } 228 }
276 229
277 /** Parse a stylesheet file. */ 230 /** Parse a stylesheet file. */
278 Future _parseCssFile(UrlInfo inputUrl) { 231 Future _parseCssFile(UrlInfo inputUrl) {
279 if (!options.emulateScopedCss || 232 if (!options.emulateScopedCss) {
280 !_pathMapper.checkInputPath(inputUrl, _messages)) {
281 return new Future<SourceFile>.value(null); 233 return new Future<SourceFile>.value(null);
282 } 234 }
283 var filePath = inputUrl.resolvedPath; 235 var filePath = inputUrl.resolvedPath;
284 return fileSystem.readText(filePath) 236 return fileSystem.readText(filePath)
285 .catchError((e) => _readError(e, inputUrl, isWarning: true)) 237 .catchError((e) => _readError(e, inputUrl, isWarning: true))
286 .then((code) { 238 .then((code) {
287 if (code == null) return; 239 if (code == null) return;
288 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET); 240 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET);
289 file.code = code; 241 file.code = code;
290 _processCssFile(inputUrl, file); 242 _processCssFile(inputUrl, file);
(...skipping 16 matching lines...) Expand all
307 259
308 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) { 260 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) {
309 if (dartFile == null) return; 261 if (dartFile == null) return;
310 262
311 files.add(dartFile); 263 files.add(dartFile);
312 264
313 var resolvedPath = inputUrl.resolvedPath; 265 var resolvedPath = inputUrl.resolvedPath;
314 var fileInfo = new FileInfo(inputUrl); 266 var fileInfo = new FileInfo(inputUrl);
315 info[resolvedPath] = fileInfo; 267 info[resolvedPath] = fileInfo;
316 fileInfo.inlinedCode = parseDartCode(resolvedPath, dartFile.code); 268 fileInfo.inlinedCode = parseDartCode(resolvedPath, dartFile.code);
317 fileInfo.outputFilename =
318 _pathMapper.mangle(path.basename(resolvedPath), '.dart', false);
319
320 _processImports(fileInfo); 269 _processImports(fileInfo);
321 } 270 }
322 271
323 void _processImports(LibraryInfo library) { 272 void _processImports(LibraryInfo library) {
324 if (library.userCode == null) return; 273 if (library.userCode == null) return;
325 274
326 for (var directive in library.userCode.directives) { 275 for (var directive in library.userCode.directives) {
327 _loadFile(_getDirectiveUrlInfo(library, directive), _parseDartFile); 276 _loadFile(_getDirectiveUrlInfo(library, directive), _parseDartFile);
328 } 277 }
329 } 278 }
(...skipping 12 matching lines...) Expand all
342 } else if (styleSheet != null) { 291 } else if (styleSheet != null) {
343 _resolveStyleSheetImports(inputUrl, cssFile.path, styleSheet); 292 _resolveStyleSheetImports(inputUrl, cssFile.path, styleSheet);
344 fileInfo.styleSheets.add(styleSheet); 293 fileInfo.styleSheets.add(styleSheet);
345 } 294 }
346 } 295 }
347 296
348 /** Load and parse all style sheets referenced with an @imports. */ 297 /** Load and parse all style sheets referenced with an @imports. */
349 void _resolveStyleSheetImports(UrlInfo inputUrl, String processingFile, 298 void _resolveStyleSheetImports(UrlInfo inputUrl, String processingFile,
350 StyleSheet styleSheet) { 299 StyleSheet styleSheet) {
351 var urlInfos = _time('CSS imports', processingFile, () => 300 var urlInfos = _time('CSS imports', processingFile, () =>
352 findImportsInStyleSheet(styleSheet, _pathMapper.packageRoot, inputUrl, 301 findImportsInStyleSheet(styleSheet, _packageRoot, inputUrl, _messages));
353 _messages));
354 302
355 for (var urlInfo in urlInfos) { 303 for (var urlInfo in urlInfos) {
356 if (urlInfo == null) break; 304 if (urlInfo == null) break;
357 // Load any @imported stylesheet files referenced in this style sheet. 305 // Load any @imported stylesheet files referenced in this style sheet.
358 _loadFile(urlInfo, _parseCssFile); 306 _loadFile(urlInfo, _parseCssFile);
359 } 307 }
360 } 308 }
361 309
362 String _directiveUri(Directive directive) { 310 String _directiveUri(Directive directive) {
363 var uriDirective = (directive as UriBasedDirective).uri; 311 var uriDirective = (directive as UriBasedDirective).uri;
364 return (uriDirective as dynamic).value; 312 return (uriDirective as dynamic).value;
365 } 313 }
366 314
367 UrlInfo _getDirectiveUrlInfo(LibraryInfo library, Directive directive) { 315 UrlInfo _getDirectiveUrlInfo(LibraryInfo library, Directive directive) {
368 var uri = _directiveUri(directive); 316 var uri = _directiveUri(directive);
369 if (uri.startsWith('dart:')) return null; 317 if (uri.startsWith('dart:')) return null;
370 if (uri.startsWith('package:') && uri.startsWith('package:polymer/')) { 318 if (uri.startsWith('package:') && uri.startsWith('package:polymer/')) {
371 // Don't process our own package -- we'll implement @observable manually. 319 // Don't process our own package -- we'll implement @observable manually.
372 return null; 320 return null;
373 } 321 }
374 322
375 var span = library.userCode.sourceFile.span( 323 var span = library.userCode.sourceFile.span(
376 directive.offset, directive.end); 324 directive.offset, directive.end);
377 return UrlInfo.resolve(uri, library.dartCodeUrl, span, 325 return UrlInfo.resolve(uri, library.dartCodeUrl, span, _packageRoot,
378 _pathMapper.packageRoot, _messages); 326 _messages);
379 } 327 }
380 328
381 /** 329 /**
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. 330 * Finds all Dart code libraries.
414 * Each library will have [LibraryInfo.inlinedCode] that is non-null. 331 * Each library will have [LibraryInfo.inlinedCode] that is non-null.
415 * Also each inlinedCode will be unique. 332 * Also each inlinedCode will be unique.
416 */ 333 */
417 List<LibraryInfo> _findAllDartLibraries() { 334 List<LibraryInfo> _findAllDartLibraries() {
418 var libs = <LibraryInfo>[]; 335 var libs = <LibraryInfo>[];
419 void _addLibrary(LibraryInfo lib) { 336 void _addLibrary(LibraryInfo lib) {
420 if (lib.inlinedCode != null) libs.add(lib); 337 if (lib.inlinedCode != null) libs.add(lib);
421 } 338 }
422 339
(...skipping 15 matching lines...) Expand all
438 throw new StateError('internal error: ' 355 throw new StateError('internal error: '
439 'duplicate user code for ${lib.dartCodeUrl.resolvedPath}.' 356 'duplicate user code for ${lib.dartCodeUrl.resolvedPath}.'
440 ' Files were: $files'); 357 ' Files were: $files');
441 } 358 }
442 seen.add(lib.inlinedCode); 359 seen.add(lib.inlinedCode);
443 } 360 }
444 return true; 361 return true;
445 } 362 }
446 363
447 /** 364 /**
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 365 * This method computes which Dart files have been modified, starting
482 * from [transformed] and marking recursively through all files that import 366 * from [transformed] and marking recursively through all files that import
483 * the modified files. 367 * the modified files.
484 */ 368 */
485 void _findModifiedDartFiles(List<LibraryInfo> libraries, 369 void _findModifiedDartFiles(List<LibraryInfo> libraries,
486 List<FileInfo> transformed) { 370 List<FileInfo> transformed) {
487 371
488 if (transformed.length == 0) return; 372 if (transformed.length == 0) return;
489 373
490 // Compute files that reference each file, then use this information to 374 // Compute files that reference each file, then use this information to
(...skipping 18 matching lines...) Expand all
509 library.referencedBy.forEach(setModified); 393 library.referencedBy.forEach(setModified);
510 } 394 }
511 transformed.forEach(setModified); 395 transformed.forEach(setModified);
512 396
513 for (var lib in libraries) { 397 for (var lib in libraries) {
514 // We don't need this anymore, so free it. 398 // We don't need this anymore, so free it.
515 lib.referencedBy = null; 399 lib.referencedBy = null;
516 } 400 }
517 } 401 }
518 402
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. */ 403 /** Run the analyzer on every input html file. */
544 void _analyze() { 404 void _analyze() {
545 var uniqueIds = new IntIterator(); 405 var uniqueIds = new IntIterator();
546 for (var file in files) { 406 for (var file in files) {
547 if (file.isHtml) { 407 if (file.isHtml) {
548 _time('Analyzed contents', file.path, () => 408 _time('Analyzed contents', file.path, () =>
549 analyzeFile(file, info, uniqueIds, global, _messages, 409 analyzeFile(file, info, uniqueIds, global, _messages,
550 options.emulateScopedCss)); 410 options.emulateScopedCss));
551 } 411 }
552 } 412 }
553 } 413 }
554 414
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 415 // TODO(jmesserly): refactor this and other CSS related transforms out of
625 // Compiler. 416 // Compiler.
626 /** 417 /**
627 * Generate an CSS file for all style sheets (main and components). 418 * Generate an CSS file for all style sheets (main and components).
628 * Returns true if a file was generated, otherwise false. 419 * Returns true if a file was generated, otherwise false.
629 */ 420 */
630 bool _emitAllCss() { 421 bool _emitAllCss() {
631 if (!options.emulateScopedCss) return false; 422 if (!options.emulateScopedCss) return false;
632 423
633 var buff = new StringBuffer(); 424 var buff = new StringBuffer();
634 425
635 // Emit all linked style sheet files first. 426 // Emit all linked style sheet files first.
636 for (var file in files) { 427 for (var file in files) {
637 var css = new StringBuffer(); 428 var css = new StringBuffer();
638 var fileInfo = info[file.path]; 429 var fileInfo = info[file.path];
639 if (file.isStyleSheet) { 430 if (file.isStyleSheet) {
640 for (var styleSheet in fileInfo.styleSheets) { 431 for (var styleSheet in fileInfo.styleSheets) {
641 // Translate any URIs in CSS. 432 // Translate any URIs in CSS.
642 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath, 433 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath,
643 options.rewriteUrls, styleSheet); 434 options.rewriteUrls, styleSheet);
644 css.write( 435 css.write(
645 '/* Auto-generated from style sheet href = ${file.path} */\n' 436 '/* Auto-generated from style sheet href = ${file.path} */\n'
646 '/* DO NOT EDIT. */\n\n'); 437 '/* DO NOT EDIT. */\n\n');
647 css.write(emitStyleSheet(styleSheet, fileInfo)); 438 css.write(emitStyleSheet(styleSheet, fileInfo));
648 css.write('\n\n'); 439 css.write('\n\n');
649 } 440 }
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 } 441 }
658 } 442 }
659 443
660 // Emit all CSS for each component (style scoped). 444 // Emit all CSS for each component (style scoped).
661 for (var file in files) { 445 for (var file in files) {
662 if (file.isHtml) { 446 if (file.isHtml) {
663 var fileInfo = info[file.path]; 447 var fileInfo = info[file.path];
664 for (var component in fileInfo.declaredComponents) { 448 for (var component in fileInfo.declaredComponents) {
665 for (var styleSheet in component.styleSheets) { 449 for (var styleSheet in component.styleSheets) {
666 // Translate any URIs in CSS. 450 // Translate any URIs in CSS.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 } 489 }
706 } 490 }
707 491
708 if (buff.isEmpty) return false; 492 if (buff.isEmpty) return false;
709 493
710 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true); 494 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true);
711 output.add(new OutputFile(cssPath, buff.toString())); 495 output.add(new OutputFile(cssPath, buff.toString()));
712 return true; 496 return true;
713 } 497 }
714 498
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(), 499 _time(String logMessage, String filePath, callback(),
759 {bool printTime: false}) { 500 {bool printTime: false}) {
760 var message = new StringBuffer(); 501 var message = new StringBuffer();
761 message.write(logMessage); 502 message.write(logMessage);
762 var filename = path.basename(filePath); 503 var filename = path.basename(filePath);
763 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) { 504 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) {
764 message.write(' '); 505 message.write(' ');
765 } 506 }
766 message.write(filename); 507 message.write(filename);
767 return time(message.toString(), callback, 508 return time(message.toString(), callback,
768 printTime: options.verbose || printTime); 509 printTime: options.verbose || printTime);
769 } 510 }
770 } 511 }
OLDNEW
« no previous file with comments | « pkg/polymer/lib/safe_html.dart ('k') | pkg/polymer/lib/src/compiler_options.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698