OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 engine.element; | 5 library engine.element; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' show min; |
8 | 9 |
9 import 'package:analyzer/src/generated/utilities_general.dart'; | 10 import 'package:analyzer/src/generated/utilities_general.dart'; |
10 import 'package:analyzer/src/task/dart.dart'; | 11 import 'package:analyzer/src/task/dart.dart'; |
11 import 'package:analyzer/task/model.dart' | 12 import 'package:analyzer/task/model.dart' |
12 show AnalysisTarget, ConstantEvaluationTarget; | 13 show AnalysisTarget, ConstantEvaluationTarget; |
13 | 14 |
14 import 'ast.dart'; | 15 import 'ast.dart'; |
15 import 'constant.dart' show EvaluationResultImpl; | 16 import 'constant.dart' show EvaluationResultImpl; |
16 import 'engine.dart' show AnalysisContext, AnalysisEngine, AnalysisException; | 17 import 'engine.dart' show AnalysisContext, AnalysisEngine, AnalysisException; |
17 import 'html.dart' show XmlAttributeNode, XmlTagNode; | 18 import 'html.dart' show XmlAttributeNode, XmlTagNode; |
(...skipping 7315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7333 */ | 7334 */ |
7334 List<ImportElement> _imports = ImportElement.EMPTY_LIST; | 7335 List<ImportElement> _imports = ImportElement.EMPTY_LIST; |
7335 | 7336 |
7336 /** | 7337 /** |
7337 * A list containing specifications of all of the exports defined in this | 7338 * A list containing specifications of all of the exports defined in this |
7338 * library. | 7339 * library. |
7339 */ | 7340 */ |
7340 List<ExportElement> _exports = ExportElement.EMPTY_LIST; | 7341 List<ExportElement> _exports = ExportElement.EMPTY_LIST; |
7341 | 7342 |
7342 /** | 7343 /** |
| 7344 * A list containing the strongly connected component in the import/export |
| 7345 * graph in which the current library resides. Computed on demand, null |
| 7346 * if not present. If _libraryCycle is set, then the _libraryCycle field |
| 7347 * for all libraries reachable from this library in the import/export graph |
| 7348 * is also set. |
| 7349 */ |
| 7350 List<LibraryElement> _libraryCycle = null; |
| 7351 |
| 7352 /** |
7343 * A list containing all of the compilation units that are included in this | 7353 * A list containing all of the compilation units that are included in this |
7344 * library using a `part` directive. | 7354 * library using a `part` directive. |
7345 */ | 7355 */ |
7346 List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST; | 7356 List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST; |
7347 | 7357 |
7348 /** | 7358 /** |
7349 * The element representing the synthetic function `loadLibrary` that is | 7359 * The element representing the synthetic function `loadLibrary` that is |
7350 * defined for this library, or `null` if the element has not yet been created
. | 7360 * defined for this library, or `null` if the element has not yet been created
. |
7351 */ | 7361 */ |
7352 FunctionElement _loadLibraryFunction; | 7362 FunctionElement _loadLibraryFunction; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7520 } | 7530 } |
7521 return false; | 7531 return false; |
7522 } | 7532 } |
7523 | 7533 |
7524 @override | 7534 @override |
7525 ElementKind get kind => ElementKind.LIBRARY; | 7535 ElementKind get kind => ElementKind.LIBRARY; |
7526 | 7536 |
7527 @override | 7537 @override |
7528 LibraryElement get library => this; | 7538 LibraryElement get library => this; |
7529 | 7539 |
| 7540 List<LibraryElement> get libraryCycle { |
| 7541 if (_libraryCycle != null) { |
| 7542 return _libraryCycle; |
| 7543 } |
| 7544 |
| 7545 // Global counter for this run of the algorithm |
| 7546 int counter = 0; |
| 7547 // The discovery times of each library |
| 7548 Map<LibraryElementImpl, int> indices = {}; |
| 7549 // The set of scc candidates |
| 7550 Set<LibraryElementImpl> active = new Set(); |
| 7551 // The stack of discovered elements |
| 7552 List<LibraryElementImpl> stack = []; |
| 7553 // For a given library that has not yet been processed by this run of the |
| 7554 // algorithm, compute the strongly connected components. |
| 7555 int scc(LibraryElementImpl library) { |
| 7556 int index = counter++; |
| 7557 int root = index; |
| 7558 indices[library] = index; |
| 7559 active.add(library); |
| 7560 stack.add(library); |
| 7561 void recurse(LibraryElementImpl child) { |
| 7562 if (!indices.containsKey(child)) { |
| 7563 // We haven't visited this child yet, so recurse on the child, |
| 7564 // returning the lowest numbered node reachable from the child. If |
| 7565 // the child can reach a root which is lower numbered than anything |
| 7566 // we've reached so far, update the root. |
| 7567 root = min(root, scc(child)); |
| 7568 } else if (active.contains(child)) { |
| 7569 // The child has been visited, but has not yet been placed into a |
| 7570 // component. If the child is higher than anything we've seen so far |
| 7571 // update the root appropriately. |
| 7572 root = min(root, indices[child]); |
| 7573 } |
| 7574 } |
| 7575 // Recurse on all of the children in the import/export graph, filtering |
| 7576 // out those for which library cycles have already been computed. |
| 7577 library.exportedLibraries |
| 7578 .where((l) => l._libraryCycle == null) |
| 7579 .forEach(recurse); |
| 7580 library.importedLibraries |
| 7581 .where((l) => l._libraryCycle == null) |
| 7582 .forEach(recurse); |
| 7583 |
| 7584 if (root == index) { |
| 7585 // This is the root of a strongly connected component. |
| 7586 // Pop the elements, and share the component across all |
| 7587 // of the elements. |
| 7588 List<LibraryElement> component = <LibraryElement>[]; |
| 7589 LibraryElementImpl cur = null; |
| 7590 do { |
| 7591 cur = stack.removeLast(); |
| 7592 active.remove(cur); |
| 7593 component.add(cur); |
| 7594 cur._libraryCycle = component; |
| 7595 } while (cur != library); |
| 7596 } |
| 7597 return root; |
| 7598 } |
| 7599 scc(library); |
| 7600 return _libraryCycle; |
| 7601 } |
| 7602 |
7530 @override | 7603 @override |
7531 FunctionElement get loadLibraryFunction { | 7604 FunctionElement get loadLibraryFunction { |
7532 if (_loadLibraryFunction == null) { | 7605 if (_loadLibraryFunction == null) { |
7533 FunctionElementImpl function = | 7606 FunctionElementImpl function = |
7534 new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1); | 7607 new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1); |
7535 function.synthetic = true; | 7608 function.synthetic = true; |
7536 function.enclosingElement = this; | 7609 function.enclosingElement = this; |
7537 function.returnType = loadLibraryReturnType; | 7610 function.returnType = loadLibraryReturnType; |
7538 function.type = new FunctionTypeImpl(function); | 7611 function.type = new FunctionTypeImpl(function); |
7539 _loadLibraryFunction = function; | 7612 _loadLibraryFunction = function; |
(...skipping 3304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10844 | 10917 |
10845 @override | 10918 @override |
10846 void visitElement(Element element) { | 10919 void visitElement(Element element) { |
10847 int offset = element.nameOffset; | 10920 int offset = element.nameOffset; |
10848 if (offset != -1) { | 10921 if (offset != -1) { |
10849 map[offset] = element; | 10922 map[offset] = element; |
10850 } | 10923 } |
10851 super.visitElement(element); | 10924 super.visitElement(element); |
10852 } | 10925 } |
10853 } | 10926 } |
OLD | NEW |