Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 /// Tracks the shape of the import/export graph and dependencies between files. | 5 /// Tracks the shape of the import/export graph and dependencies between files. |
| 6 library dev_compiler.src.dependency_graph; | 6 library dev_compiler.src.dependency_graph; |
| 7 | 7 |
| 8 import 'dart:collection' show HashSet, HashMap; | 8 import 'dart:collection' show HashSet, HashMap; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' show parseDirectives; | 10 import 'package:analyzer/analyzer.dart' show parseDirectives; |
| 11 import 'package:analyzer/src/generated/ast.dart' | 11 import 'package:analyzer/src/generated/ast.dart' |
| 12 show | 12 show |
| 13 AstNode, | 13 AstNode, |
| 14 CompilationUnit, | 14 CompilationUnit, |
| 15 ExportDirective, | 15 ExportDirective, |
| 16 Identifier, | 16 Identifier, |
| 17 ImportDirective, | 17 ImportDirective, |
| 18 LibraryDirective, | 18 LibraryDirective, |
| 19 PartDirective, | 19 PartDirective, |
| 20 PartOfDirective, | 20 PartOfDirective, |
| 21 UriBasedDirective; | 21 UriBasedDirective; |
| 22 import 'package:analyzer/src/generated/engine.dart' | 22 import 'package:analyzer/src/generated/engine.dart' |
| 23 show ParseDartTask, AnalysisContext; | 23 show ParseDartTask, AnalysisContext; |
| 24 import 'package:analyzer/src/generated/error.dart'; | |
| 24 import 'package:analyzer/src/generated/source.dart' show Source, SourceKind; | 25 import 'package:analyzer/src/generated/source.dart' show Source, SourceKind; |
| 25 import 'package:html/dom.dart' show Document, Node, Element; | 26 import 'package:html/dom.dart' show Document, Node, Element; |
| 26 import 'package:html/parser.dart' as html; | 27 import 'package:html/parser.dart' as html; |
| 27 import 'package:logging/logging.dart' show Logger, Level; | 28 import 'package:logging/logging.dart' show Logger, Level; |
| 28 import 'package:path/path.dart' as path; | 29 import 'package:path/path.dart' as path; |
| 29 | 30 |
| 30 import 'info.dart'; | 31 import 'info.dart'; |
| 31 import 'options.dart'; | 32 import 'options.dart'; |
| 32 import 'report.dart'; | 33 import 'report.dart'; |
| 33 | 34 |
| 34 /// Holds references to all source nodes in the import graph. This is mainly | 35 /// Holds references to all source nodes in the import graph. This is mainly |
| 35 /// used as a level of indirection to ensure that each source has a canonical | 36 /// used as a level of indirection to ensure that each source has a canonical |
| 36 /// representation. | 37 /// representation. |
| 37 class SourceGraph { | 38 class SourceGraph { |
| 38 /// All nodes in the source graph. Used to get a canonical representation for | 39 /// All nodes in the source graph. Used to get a canonical representation for |
| 39 /// any node. | 40 /// any node. |
| 40 final Map<Uri, SourceNode> nodes = {}; | 41 final Map<Uri, SourceNode> nodes = {}; |
| 41 | 42 |
| 42 /// Resources included by default on any application. | 43 /// Resources included by default on any application. |
| 43 final runtimeDeps = new Set<ResourceSourceNode>(); | 44 final runtimeDeps = new Set<ResourceSourceNode>(); |
| 44 | 45 |
| 45 /// Analyzer used to resolve source files. | 46 /// Analyzer used to resolve source files. |
| 46 final AnalysisContext _context; | 47 final AnalysisContext _context; |
| 47 final CompilerReporter _reporter; | 48 final AnalysisErrorListener _reporter; |
| 48 final CompilerOptions _options; | 49 final CompilerOptions _options; |
| 49 | 50 |
| 50 SourceGraph(this._context, this._reporter, this._options) { | 51 SourceGraph(this._context, this._reporter, this._options) { |
| 51 var dir = _options.runtimeDir; | 52 var dir = _options.runtimeDir; |
| 52 if (dir == null) { | 53 if (dir == null) { |
| 53 _log.severe('Runtime dir could not be determined automatically, ' | 54 _log.severe('Runtime dir could not be determined automatically, ' |
| 54 'please specify the --runtime-dir flag on the command line.'); | 55 'please specify the --runtime-dir flag on the command line.'); |
| 55 return; | 56 return; |
| 56 } | 57 } |
| 57 var prefix = path.absolute(dir); | 58 var prefix = path.absolute(dir); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 final htmlResourceNodes = new HashMap<Element, ResourceSourceNode>(); | 175 final htmlResourceNodes = new HashMap<Element, ResourceSourceNode>(); |
| 175 | 176 |
| 176 HtmlSourceNode(SourceGraph graph, Uri uri, Source source) | 177 HtmlSourceNode(SourceGraph graph, Uri uri, Source source) |
| 177 : runtimeDeps = graph.runtimeDeps, | 178 : runtimeDeps = graph.runtimeDeps, |
| 178 super(graph, uri, source); | 179 super(graph, uri, source); |
| 179 | 180 |
| 180 @override | 181 @override |
| 181 void update() { | 182 void update() { |
| 182 super.update(); | 183 super.update(); |
| 183 if (needsRebuild) { | 184 if (needsRebuild) { |
| 184 graph._reporter.clearHtml(uri); | 185 var reporter = graph._reporter; |
| 186 if (reporter is SummaryReporter) { | |
| 187 reporter.clearHtml(uri); | |
| 188 } | |
| 185 document = html.parse(contents, generateSpans: true); | 189 document = html.parse(contents, generateSpans: true); |
| 186 var newScripts = new Set<DartSourceNode>(); | 190 var newScripts = new Set<DartSourceNode>(); |
| 187 var tags = document.querySelectorAll('script[type="application/dart"]'); | 191 var tags = document.querySelectorAll('script[type="application/dart"]'); |
| 188 for (var script in tags) { | 192 for (var script in tags) { |
| 189 var src = script.attributes['src']; | 193 var src = script.attributes['src']; |
| 190 if (src == null) { | 194 if (src == null) { |
| 191 _reportError(graph, 'inlined script tags not supported at this time ' | 195 _reportError(graph, 'inlined script tags not supported at this time ' |
| 192 '(see https://github.com/dart-lang/dart-dev-compiler/issues/54).', | 196 '(see https://github.com/dart-lang/dart-dev-compiler/issues/54).', |
| 193 script); | 197 script); |
| 194 continue; | 198 continue; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 225 newResources.add(res); | 229 newResources.add(res); |
| 226 } | 230 } |
| 227 if (!_same(newResources, resources)) { | 231 if (!_same(newResources, resources)) { |
| 228 structureChanged = true; | 232 structureChanged = true; |
| 229 resources = newResources; | 233 resources = newResources; |
| 230 } | 234 } |
| 231 } | 235 } |
| 232 } | 236 } |
| 233 | 237 |
| 234 void _reportError(SourceGraph graph, String message, Node node) { | 238 void _reportError(SourceGraph graph, String message, Node node) { |
| 235 graph._reporter.enterHtml(_source.uri); | |
| 236 var span = node.sourceSpan; | 239 var span = node.sourceSpan; |
| 237 graph._reporter.log( | 240 |
| 238 new Message(message, Level.SEVERE, span.start.offset, span.end.offset)); | 241 // TODO(jmesserly): should these be errors or warnings? |
|
vsm
2015/07/09 23:54:07
Mostly look like real errors (e.g., inline scripts
Jennifer Messerly
2015/07/10 16:12:05
yeah, maybe ... on the other hand, HTML doesn't re
| |
| 239 graph._reporter.leaveHtml(); | 242 var errorCode = new HtmlWarningCode('dev_compiler.$runtimeType', message); |
| 243 graph._reporter.onError(new AnalysisError( | |
| 244 _source, span.start.offset, span.length, errorCode)); | |
| 240 } | 245 } |
| 241 } | 246 } |
| 242 | 247 |
| 243 /// A node representing a Dart library or part. | 248 /// A node representing a Dart library or part. |
| 244 class DartSourceNode extends SourceNode { | 249 class DartSourceNode extends SourceNode { |
| 245 /// Set of imported libraries (empty for part files). | 250 /// Set of imported libraries (empty for part files). |
| 246 Set<DartSourceNode> imports = new Set<DartSourceNode>(); | 251 Set<DartSourceNode> imports = new Set<DartSourceNode>(); |
| 247 | 252 |
| 248 /// Set of exported libraries (empty for part files). | 253 /// Set of exported libraries (empty for part files). |
| 249 Set<DartSourceNode> exports = new Set<DartSourceNode>(); | 254 Set<DartSourceNode> exports = new Set<DartSourceNode>(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 274 // But we could discard it after that point. | 279 // But we could discard it after that point. |
| 275 void saveUpdatedContents() { | 280 void saveUpdatedContents() { |
| 276 graph._context.setContents(_source, _source.contents.data); | 281 graph._context.setContents(_source, _source.contents.data); |
| 277 } | 282 } |
| 278 | 283 |
| 279 @override | 284 @override |
| 280 void update() { | 285 void update() { |
| 281 super.update(); | 286 super.update(); |
| 282 | 287 |
| 283 if (needsRebuild) { | 288 if (needsRebuild) { |
| 284 graph._reporter.clearLibrary(uri); | 289 var reporter = graph._reporter; |
| 290 if (reporter is SummaryReporter) { | |
| 291 reporter.clearLibrary(uri); | |
| 292 } | |
| 293 | |
| 285 // If the defining compilation-unit changed, the structure might have | 294 // If the defining compilation-unit changed, the structure might have |
| 286 // changed. | 295 // changed. |
| 287 var unit = parseDirectives(contents, name: _source.fullName); | 296 var unit = parseDirectives(contents, name: _source.fullName); |
| 288 var newImports = new Set<DartSourceNode>(); | 297 var newImports = new Set<DartSourceNode>(); |
| 289 var newExports = new Set<DartSourceNode>(); | 298 var newExports = new Set<DartSourceNode>(); |
| 290 var newParts = new Set<DartSourceNode>(); | 299 var newParts = new Set<DartSourceNode>(); |
| 291 for (var d in unit.directives) { | 300 for (var d in unit.directives) { |
| 292 // Nothing to do for parts. | 301 // Nothing to do for parts. |
| 293 if (d is PartOfDirective) return; | 302 if (d is PartOfDirective) return; |
| 294 if (d is LibraryDirective) continue; | 303 if (d is LibraryDirective) continue; |
| 295 | 304 |
| 296 var directiveUri = (d as UriBasedDirective).uri; | 305 var directiveUri = (d as UriBasedDirective).uri; |
| 297 | 306 |
| 298 // `dart:core` and other similar URLs only contain a name, but it is | 307 // `dart:core` and other similar URLs only contain a name, but it is |
| 299 // meant to be a folder when resolving relative paths from it. | 308 // meant to be a folder when resolving relative paths from it. |
| 300 var targetUri = uri.scheme == 'dart' && uri.pathSegments.length == 1 | 309 var targetUri = uri.scheme == 'dart' && uri.pathSegments.length == 1 |
| 301 ? Uri.parse('$uri/').resolve(directiveUri.stringValue) | 310 ? Uri.parse('$uri/').resolve(directiveUri.stringValue) |
| 302 : uri.resolve(directiveUri.stringValue); | 311 : uri.resolve(directiveUri.stringValue); |
| 303 var target = | 312 var target = |
| 304 ParseDartTask.resolveDirective(graph._context, _source, d, null); | 313 ParseDartTask.resolveDirective(graph._context, _source, d, null); |
| 305 var node = graph.nodes.putIfAbsent( | 314 var node = graph.nodes.putIfAbsent( |
| 306 targetUri, () => new DartSourceNode(graph, targetUri, target)); | 315 targetUri, () => new DartSourceNode(graph, targetUri, target)); |
| 307 //var node = graph.nodeFromUri(targetUri); | 316 //var node = graph.nodeFromUri(targetUri); |
| 308 if (node._source == null || !node._source.exists()) { | 317 if (node._source == null || !node._source.exists()) { |
| 309 _reportError(graph, 'File $targetUri not found', unit, d); | 318 _reportError(graph, 'File $targetUri not found', d); |
| 310 } | 319 } |
| 311 | 320 |
| 312 if (d is ImportDirective) { | 321 if (d is ImportDirective) { |
| 313 newImports.add(node); | 322 newImports.add(node); |
| 314 } else if (d is ExportDirective) { | 323 } else if (d is ExportDirective) { |
| 315 newExports.add(node); | 324 newExports.add(node); |
| 316 } else if (d is PartDirective) { | 325 } else if (d is PartDirective) { |
| 317 newParts.add(node); | 326 newParts.add(node); |
| 318 } | 327 } |
| 319 } | 328 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 for (var p in parts) { | 362 for (var p in parts) { |
| 354 // Technically for parts we don't need to look at the contents. If they | 363 // Technically for parts we don't need to look at the contents. If they |
| 355 // contain imports, exports, or parts, we'll ignore them in our crawling. | 364 // contain imports, exports, or parts, we'll ignore them in our crawling. |
| 356 // However we do a full update to make it easier to adjust when users | 365 // However we do a full update to make it easier to adjust when users |
| 357 // switch a file from a part to a library. | 366 // switch a file from a part to a library. |
| 358 p.update(); | 367 p.update(); |
| 359 if (p.needsRebuild) needsRebuild = true; | 368 if (p.needsRebuild) needsRebuild = true; |
| 360 } | 369 } |
| 361 } | 370 } |
| 362 | 371 |
| 363 void _reportError( | 372 void _reportError(SourceGraph graph, String message, AstNode node) { |
| 364 SourceGraph graph, String message, CompilationUnit unit, AstNode node) { | 373 graph._reporter.onError(new AnalysisError(_source, node.offset, |
| 365 graph._reporter | 374 node.length, new CompileTimeErrorCode('dev_compiler.$runtimeType', messa ge))); |
| 366 ..enterLibrary(_source.uri) | |
| 367 ..enterCompilationUnit(unit, _source) | |
| 368 ..log(new Message(message, Level.SEVERE, node.offset, node.end)) | |
| 369 ..leaveCompilationUnit() | |
| 370 ..leaveLibrary(); | |
| 371 } | 375 } |
| 372 } | 376 } |
| 373 | 377 |
| 374 /// Represents a runtime resource from our compiler that is needed to run an | 378 /// Represents a runtime resource from our compiler that is needed to run an |
| 375 /// application. | 379 /// application. |
| 376 class ResourceSourceNode extends SourceNode { | 380 class ResourceSourceNode extends SourceNode { |
| 377 ResourceSourceNode(graph, uri, source) : super(graph, uri, source); | 381 ResourceSourceNode(graph, uri, source) : super(graph, uri, source); |
| 378 } | 382 } |
| 379 | 383 |
| 380 /// Updates the structure and `needsRebuild` marks in nodes of [graph] reachable | 384 /// Updates the structure and `needsRebuild` marks in nodes of [graph] reachable |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 // _foreign_helper is not included, as it only defines the JS builtin that | 543 // _foreign_helper is not included, as it only defines the JS builtin that |
| 540 // the compiler handles at compile time. | 544 // the compiler handles at compile time. |
| 541 ]; | 545 ]; |
| 542 | 546 |
| 543 /// Runtime files added to applications when running in server mode. | 547 /// Runtime files added to applications when running in server mode. |
| 544 List<String> runtimeFilesForServerMode([bool includeWidget = true]) => | 548 List<String> runtimeFilesForServerMode([bool includeWidget = true]) => |
| 545 new List<String>.from(defaultRuntimeFiles) | 549 new List<String>.from(defaultRuntimeFiles) |
| 546 ..addAll(includeWidget ? const ['messages_widget.js', 'messages.css'] : []); | 550 ..addAll(includeWidget ? const ['messages_widget.js', 'messages.css'] : []); |
| 547 | 551 |
| 548 final _log = new Logger('dev_compiler.dependency_graph'); | 552 final _log = new Logger('dev_compiler.dependency_graph'); |
| OLD | NEW |