| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'dart:core' hide Resource; | 7 import 'dart:core' hide Resource; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 CompilationUnit partUnit = _parse(partSource, strong); | 181 CompilationUnit partUnit = _parse(partSource, strong); |
| 182 assembler.addUnlinkedUnit(partSource, serializeAstUnlinked(partUnit)); | 182 assembler.addUnlinkedUnit(partSource, serializeAstUnlinked(partUnit)); |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 // Add the SDK and the unlinked extension bundle. | 185 // Add the SDK and the unlinked extension bundle. |
| 186 PackageBundleBuilder unlinkedBuilder = assembler.assemble(); | 186 PackageBundleBuilder unlinkedBuilder = assembler.assemble(); |
| 187 SummaryDataStore store = new SummaryDataStore(const <String>[]); | 187 SummaryDataStore store = new SummaryDataStore(const <String>[]); |
| 188 store.addBundle(null, sdkBundle); | 188 store.addBundle(null, sdkBundle); |
| 189 store.addBundle(null, unlinkedBuilder); | 189 store.addBundle(null, unlinkedBuilder); |
| 190 // Link the extension bundle. | 190 // Link the extension bundle. |
| 191 bool failed = false; | 191 Map<String, LinkedLibraryBuilder> linkedLibraries; |
| 192 Map<String, LinkedLibraryBuilder> linkedLibraries = | 192 try { |
| 193 link([libUriStr].toSet(), (String absoluteUri) { | 193 linkedLibraries = link([libUriStr].toSet(), (String absoluteUri) { |
| 194 LinkedLibrary dependencyLibrary = store.linkedMap[absoluteUri]; | 194 LinkedLibrary dependencyLibrary = store.linkedMap[absoluteUri]; |
| 195 if (dependencyLibrary == null) { | 195 if (dependencyLibrary == null) { |
| 196 failed = true; | 196 throw new _LinkException(); |
| 197 } | 197 } |
| 198 return dependencyLibrary; | 198 return dependencyLibrary; |
| 199 }, (String absoluteUri) { | 199 }, (String absoluteUri) { |
| 200 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absoluteUri]; | 200 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absoluteUri]; |
| 201 if (unlinkedUnit == null) { | 201 if (unlinkedUnit == null) { |
| 202 failed = true; | 202 throw new _LinkException(); |
| 203 } | 203 } |
| 204 return unlinkedUnit; | 204 return unlinkedUnit; |
| 205 }, strong); | 205 }, strong); |
| 206 if (failed || linkedLibraries.length != 1) { | 206 } on _LinkException { |
| 207 return null; |
| 208 } |
| 209 if (linkedLibraries.length != 1) { |
| 207 return null; | 210 return null; |
| 208 } | 211 } |
| 209 // Append linked libraries into the assembler. | 212 // Append linked libraries into the assembler. |
| 210 linkedLibraries.forEach((uri, library) { | 213 linkedLibraries.forEach((uri, library) { |
| 211 assembler.addLinkedLibrary(uri, library); | 214 assembler.addLinkedLibrary(uri, library); |
| 212 }); | 215 }); |
| 213 List<int> bytes = assembler.assemble().toBuffer(); | 216 List<int> bytes = assembler.assemble().toBuffer(); |
| 214 return new PackageBundle.fromBuffer(bytes); | 217 return new PackageBundle.fromBuffer(bytes); |
| 215 } on FileSystemException { | 218 } on FileSystemException { |
| 216 return null; | 219 return null; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 PackageBundle extension = computeSdkExtension(context, sdkBundle); | 257 PackageBundle extension = computeSdkExtension(context, sdkBundle); |
| 255 if (extension != null) { | 258 if (extension != null) { |
| 256 store.addBundle(null, extension); | 259 store.addBundle(null, extension); |
| 257 } | 260 } |
| 258 } | 261 } |
| 259 for (PackageBundle unlinked in unlinkedBundles.values) { | 262 for (PackageBundle unlinked in unlinkedBundles.values) { |
| 260 store.addBundle(null, unlinked); | 263 store.addBundle(null, unlinked); |
| 261 } | 264 } |
| 262 | 265 |
| 263 // Link each package node. | 266 // Link each package node. |
| 267 // Stopwatch linkTimer = new Stopwatch()..start(); |
| 264 for (_LinkedNode node in nodes) { | 268 for (_LinkedNode node in nodes) { |
| 265 if (!node.isEvaluated) { | 269 if (!node.isEvaluated) { |
| 266 bool strong = context.analysisOptions.strongMode; | 270 try { |
| 267 new _LinkedWalker(store, strong).walk(node); | 271 bool strong = context.analysisOptions.strongMode; |
| 272 new _LinkedWalker(store, strong).walk(node); |
| 273 } on _LinkException { |
| 274 // Linking of the node failed. |
| 275 } |
| 268 } | 276 } |
| 269 } | 277 } |
| 278 // TODO(scheglov) remove debug output after optimizing |
| 279 // print('LINKED ${unlinkedBundles.length} bundles' |
| 280 // ' in ${linkTimer.elapsedMilliseconds} ms'); |
| 270 | 281 |
| 271 // Create successfully linked packages. | 282 // Create successfully linked packages. |
| 272 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[]; | 283 List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[]; |
| 273 for (_LinkedNode node in nodes) { | 284 for (_LinkedNode node in nodes) { |
| 274 if (node.linkedBuilder != null) { | 285 if (node.linkedBuilder != null) { |
| 275 List<int> bytes = node.linkedBuilder.toBuffer(); | 286 List<int> bytes = node.linkedBuilder.toBuffer(); |
| 276 PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes); | 287 PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes); |
| 277 linkedPackages.add( | 288 linkedPackages.add( |
| 278 new LinkedPubPackage(node.package, node.unlinked, linkedBundle)); | 289 new LinkedPubPackage(node.package, node.unlinked, linkedBundle)); |
| 279 } | 290 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 return bundle; | 426 return bundle; |
| 416 } | 427 } |
| 417 // Try to read from the file system. | 428 // Try to read from the file system. |
| 418 String fileName = _getUnlinkedName(strong); | 429 String fileName = _getUnlinkedName(strong); |
| 419 File unlinkedFile = package.folder.getChildAssumingFile(fileName); | 430 File unlinkedFile = package.folder.getChildAssumingFile(fileName); |
| 420 if (unlinkedFile.exists) { | 431 if (unlinkedFile.exists) { |
| 421 try { | 432 try { |
| 422 List<int> bytes = unlinkedFile.readAsBytesSync(); | 433 List<int> bytes = unlinkedFile.readAsBytesSync(); |
| 423 bundle = new PackageBundle.fromBuffer(bytes); | 434 bundle = new PackageBundle.fromBuffer(bytes); |
| 424 unlinkedBundleMap[package] = bundle; | 435 unlinkedBundleMap[package] = bundle; |
| 436 // TODO(scheglov) if not in the pub cache, check for consistency |
| 425 return bundle; | 437 return bundle; |
| 426 } on FileSystemException { | 438 } on FileSystemException { |
| 427 // Ignore file system exceptions. | 439 // Ignore file system exceptions. |
| 428 } | 440 } |
| 429 } | 441 } |
| 430 // Schedule computation in the background, if in the pub cache. | 442 // Schedule computation in the background, if in the pub cache. |
| 431 if (isPathInPubCache(pathContext, package.folder.path)) { | 443 if (isPathInPubCache(pathContext, package.folder.path)) { |
| 432 if (seenPackages.add(package)) { | 444 if (seenPackages.add(package)) { |
| 433 if (packagesToComputeUnlinked.isEmpty) { | 445 if (packagesToComputeUnlinked.isEmpty) { |
| 434 _scheduleNextUnlinked(); | 446 _scheduleNextUnlinked(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 PackageBundleBuilder linkedBuilder; | 535 PackageBundleBuilder linkedBuilder; |
| 524 bool failed = false; | 536 bool failed = false; |
| 525 | 537 |
| 526 _LinkedNode(this.package, this.unlinked, this.packageToNode); | 538 _LinkedNode(this.package, this.unlinked, this.packageToNode); |
| 527 | 539 |
| 528 @override | 540 @override |
| 529 bool get isEvaluated => linkedBuilder != null || failed; | 541 bool get isEvaluated => linkedBuilder != null || failed; |
| 530 | 542 |
| 531 @override | 543 @override |
| 532 List<_LinkedNode> computeDependencies() { | 544 List<_LinkedNode> computeDependencies() { |
| 545 if (failed) { |
| 546 return const <_LinkedNode>[]; |
| 547 } |
| 548 |
| 533 Set<_LinkedNode> dependencies = new Set<_LinkedNode>(); | 549 Set<_LinkedNode> dependencies = new Set<_LinkedNode>(); |
| 534 | 550 |
| 535 void appendDependency(String uriStr) { | 551 void appendDependency(String uriStr) { |
| 536 Uri uri = FastUri.parse(uriStr); | 552 Uri uri = FastUri.parse(uriStr); |
| 537 if (!uri.hasScheme) { | 553 if (!uri.hasScheme) { |
| 538 // A relative path in this package, skip it. | 554 // A relative path in this package, skip it. |
| 539 } else if (uri.scheme == 'dart') { | 555 } else if (uri.scheme == 'dart') { |
| 540 // Dependency on the SDK is implicit and always added. | 556 // Dependency on the SDK is implicit and always added. |
| 541 // The SDK linked bundle is precomputed before linking packages. | 557 // The SDK linked bundle is precomputed before linking packages. |
| 542 } else if (uriStr.startsWith('package:')) { | 558 } else if (uriStr.startsWith('package:')) { |
| 543 String package = PubSummaryManager.getPackageName(uriStr); | 559 String package = PubSummaryManager.getPackageName(uriStr); |
| 544 _LinkedNode packageNode = packageToNode[package]; | 560 _LinkedNode packageNode = packageToNode[package]; |
| 545 if (packageNode == null) { | 561 if (packageNode == null) { |
| 546 failed = true; | 562 failed = true; |
| 563 throw new _LinkException(); |
| 547 } | 564 } |
| 548 dependencies.add(packageNode); | 565 dependencies.add(packageNode); |
| 549 } else { | 566 } else { |
| 550 failed = true; | 567 failed = true; |
| 568 throw new _LinkException(); |
| 551 } | 569 } |
| 552 } | 570 } |
| 553 | 571 |
| 554 for (UnlinkedUnit unit in unlinked.unlinkedUnits) { | 572 for (UnlinkedUnit unit in unlinked.unlinkedUnits) { |
| 555 for (UnlinkedImport import in unit.imports) { | 573 for (UnlinkedImport import in unit.imports) { |
| 556 if (!import.isImplicit) { | 574 if (!import.isImplicit) { |
| 557 appendDependency(import.uri); | 575 appendDependency(import.uri); |
| 558 } | 576 } |
| 559 } | 577 } |
| 560 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | 578 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { |
| 561 appendDependency(export.uri); | 579 appendDependency(export.uri); |
| 562 } | 580 } |
| 563 } | 581 } |
| 564 | 582 |
| 565 if (failed) { | |
| 566 return const <_LinkedNode>[]; | |
| 567 } | |
| 568 return dependencies.toList(); | 583 return dependencies.toList(); |
| 569 } | 584 } |
| 570 | 585 |
| 571 @override | 586 @override |
| 572 String toString() => package.toString(); | 587 String toString() => package.toString(); |
| 573 } | 588 } |
| 574 | 589 |
| 575 /** | 590 /** |
| 576 * Specialization of [DependencyWalker] for linking packages. | 591 * Specialization of [DependencyWalker] for linking packages. |
| 577 */ | 592 */ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 589 @override | 604 @override |
| 590 void evaluateScc(List<_LinkedNode> scc) { | 605 void evaluateScc(List<_LinkedNode> scc) { |
| 591 Map<String, _LinkedNode> uriToNode = <String, _LinkedNode>{}; | 606 Map<String, _LinkedNode> uriToNode = <String, _LinkedNode>{}; |
| 592 for (_LinkedNode node in scc) { | 607 for (_LinkedNode node in scc) { |
| 593 for (String uri in node.unlinked.unlinkedUnitUris) { | 608 for (String uri in node.unlinked.unlinkedUnitUris) { |
| 594 uriToNode[uri] = node; | 609 uriToNode[uri] = node; |
| 595 } | 610 } |
| 596 } | 611 } |
| 597 Set<String> libraryUris = uriToNode.keys.toSet(); | 612 Set<String> libraryUris = uriToNode.keys.toSet(); |
| 598 // Perform linking. | 613 // Perform linking. |
| 599 bool failed = false; | |
| 600 Map<String, LinkedLibraryBuilder> linkedLibraries = | 614 Map<String, LinkedLibraryBuilder> linkedLibraries = |
| 601 link(libraryUris, (String absoluteUri) { | 615 link(libraryUris, (String absoluteUri) { |
| 602 LinkedLibrary dependencyLibrary = store.linkedMap[absoluteUri]; | 616 LinkedLibrary dependencyLibrary = store.linkedMap[absoluteUri]; |
| 603 if (dependencyLibrary == null) { | 617 if (dependencyLibrary == null) { |
| 604 failed = true; | 618 scc.forEach((node) => node.failed = true); |
| 619 throw new _LinkException(); |
| 605 } | 620 } |
| 606 return dependencyLibrary; | 621 return dependencyLibrary; |
| 607 }, (String absoluteUri) { | 622 }, (String absoluteUri) { |
| 608 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absoluteUri]; | 623 UnlinkedUnit unlinkedUnit = store.unlinkedMap[absoluteUri]; |
| 609 if (unlinkedUnit == null) { | 624 if (unlinkedUnit == null) { |
| 610 failed = true; | 625 scc.forEach((node) => node.failed = true); |
| 626 throw new _LinkException(); |
| 611 } | 627 } |
| 612 return unlinkedUnit; | 628 return unlinkedUnit; |
| 613 }, strong); | 629 }, strong); |
| 614 // Assemble linked bundles and put them into the store. | 630 // Assemble linked bundles and put them into the store. |
| 615 if (!failed) { | 631 for (_LinkedNode node in scc) { |
| 616 for (_LinkedNode node in scc) { | 632 PackageBundleAssembler assembler = new PackageBundleAssembler(); |
| 617 PackageBundleAssembler assembler = new PackageBundleAssembler(); | 633 linkedLibraries.forEach((uri, linkedLibrary) { |
| 618 linkedLibraries.forEach((uri, linkedLibrary) { | 634 if (identical(uriToNode[uri], node)) { |
| 619 if (identical(uriToNode[uri], node)) { | 635 assembler.addLinkedLibrary(uri, linkedLibrary); |
| 620 assembler.addLinkedLibrary(uri, linkedLibrary); | 636 } |
| 621 } | 637 }); |
| 622 }); | 638 node.linkedBuilder = assembler.assemble(); |
| 623 node.linkedBuilder = assembler.assemble(); | 639 store.addBundle(null, node.linkedBuilder); |
| 624 store.addBundle(null, node.linkedBuilder); | |
| 625 } | |
| 626 } else { | |
| 627 scc.forEach((node) => node.failed = true); | |
| 628 } | 640 } |
| 629 } | 641 } |
| 630 } | 642 } |
| 643 |
| 644 /** |
| 645 * This exception is thrown during linking as a signal that linking of the |
| 646 * current bundle cannot be performed, e.g. when a dependency cannot be found. |
| 647 */ |
| 648 class _LinkException {} |
| OLD | NEW |