OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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:typed_data'; | 6 import 'dart:typed_data'; |
7 | 7 |
8 import 'package:crypto/crypto.dart'; | 8 import 'package:crypto/crypto.dart'; |
9 import 'package:front_end/file_system.dart'; | 9 import 'package:front_end/file_system.dart'; |
10 import 'package:front_end/src/base/api_signature.dart'; | 10 import 'package:front_end/src/base/api_signature.dart'; |
(...skipping 26 matching lines...) Expand all Loading... |
37 | 37 |
38 /// The absolute URI of the file. | 38 /// The absolute URI of the file. |
39 final Uri uri; | 39 final Uri uri; |
40 | 40 |
41 /// The resolved URI of the file in the file system. | 41 /// The resolved URI of the file in the file system. |
42 final Uri fileUri; | 42 final Uri fileUri; |
43 | 43 |
44 bool _exists; | 44 bool _exists; |
45 List<int> _content; | 45 List<int> _content; |
46 List<int> _contentHash; | 46 List<int> _contentHash; |
| 47 bool _hasMixinApplication; |
47 List<int> _apiSignature; | 48 List<int> _apiSignature; |
48 | 49 |
49 List<NamespaceExport> _exports; | 50 List<NamespaceExport> _exports; |
50 List<FileState> _importedLibraries; | 51 List<FileState> _importedLibraries; |
51 List<FileState> _exportedLibraries; | 52 List<FileState> _exportedLibraries; |
52 List<FileState> _partFiles; | 53 List<FileState> _partFiles; |
53 | 54 |
54 Set<FileState> _directReferencedFiles = new Set<FileState>(); | 55 Set<FileState> _directReferencedFiles = new Set<FileState>(); |
55 List<FileState> _directReferencedLibraries = <FileState>[]; | 56 List<FileState> _directReferencedLibraries = <FileState>[]; |
56 | 57 |
(...skipping 21 matching lines...) Expand all Loading... |
78 | 79 |
79 /// The list of the libraries exported by this library. | 80 /// The list of the libraries exported by this library. |
80 List<FileState> get exportedLibraries => _exportedLibraries; | 81 List<FileState> get exportedLibraries => _exportedLibraries; |
81 | 82 |
82 /// The list of the exported files with combinators. | 83 /// The list of the exported files with combinators. |
83 List<NamespaceExport> get exports => _exports; | 84 List<NamespaceExport> get exports => _exports; |
84 | 85 |
85 @override | 86 @override |
86 int get hashCode => uri.hashCode; | 87 int get hashCode => uri.hashCode; |
87 | 88 |
| 89 /// Whether the file has a mixin application. |
| 90 bool get hasMixinApplication => _hasMixinApplication; |
| 91 |
| 92 /// Whether a unit of the library has a mixin application. |
| 93 bool get hasMixinApplicationLibrary { |
| 94 return _hasMixinApplication || |
| 95 _partFiles.any((part) => part._hasMixinApplication); |
| 96 } |
| 97 |
88 /// The list of the libraries imported by this library. | 98 /// The list of the libraries imported by this library. |
89 List<FileState> get importedLibraries => _importedLibraries; | 99 List<FileState> get importedLibraries => _importedLibraries; |
90 | 100 |
91 /// The list of files this library file references as parts. | 101 /// The list of files this library file references as parts. |
92 List<FileState> get partFiles => _partFiles; | 102 List<FileState> get partFiles => _partFiles; |
93 | 103 |
94 /// Return topologically sorted cycles of dependencies for this library. | 104 /// Return topologically sorted cycles of dependencies for this library. |
95 List<LibraryCycle> get topologicalOrder { | 105 List<LibraryCycle> get topologicalOrder { |
96 var libraryWalker = new _LibraryWalker(); | 106 var libraryWalker = new _LibraryWalker(); |
97 libraryWalker.walk(libraryWalker.getNode(this)); | 107 libraryWalker.walk(libraryWalker.getNode(this)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 _content = new Uint8List(0); | 141 _content = new Uint8List(0); |
132 _exists = false; | 142 _exists = false; |
133 } | 143 } |
134 | 144 |
135 // Compute the content hash. | 145 // Compute the content hash. |
136 _contentHash = md5.convert(_content).bytes; | 146 _contentHash = md5.convert(_content).bytes; |
137 | 147 |
138 // Scan the content. | 148 // Scan the content. |
139 ScannerResult scanResult = _scan(); | 149 ScannerResult scanResult = _scan(); |
140 | 150 |
141 // Compute the API signature. | 151 // Compute syntactic properties. |
142 _apiSignature = _computeApiSignature(scanResult.tokens); | 152 _computeSyntacticProperties(scanResult.tokens); |
143 | 153 |
144 // Parse directives. | 154 // Parse directives. |
145 var listener = new _DirectiveListenerWithNative(); | 155 var listener = new _DirectiveListenerWithNative(); |
146 new TopLevelParser(listener).parseUnit(scanResult.tokens); | 156 new TopLevelParser(listener).parseUnit(scanResult.tokens); |
147 | 157 |
148 // Build the graph. | 158 // Build the graph. |
149 _importedLibraries = <FileState>[]; | 159 _importedLibraries = <FileState>[]; |
150 _exportedLibraries = <FileState>[]; | 160 _exportedLibraries = <FileState>[]; |
151 _partFiles = <FileState>[]; | 161 _partFiles = <FileState>[]; |
152 _exports = <NamespaceExport>[]; | 162 _exports = <NamespaceExport>[]; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 if (uri.toString() != 'dart:core') return; | 213 if (uri.toString() != 'dart:core') return; |
204 for (String uri in new VmTarget(null).extraRequiredLibraries) { | 214 for (String uri in new VmTarget(null).extraRequiredLibraries) { |
205 FileState file = await _getFileForRelativeUri(uri); | 215 FileState file = await _getFileForRelativeUri(uri); |
206 // TODO(scheglov) add error handling | 216 // TODO(scheglov) add error handling |
207 if (file != null) { | 217 if (file != null) { |
208 _importedLibraries.add(file); | 218 _importedLibraries.add(file); |
209 } | 219 } |
210 } | 220 } |
211 } | 221 } |
212 | 222 |
213 /// Compute and return the API signature of the file. | 223 /// Compute syntactic properties of the file: [_apiSignature] and [_hasMixinAp
plication]. |
214 /// | 224 /// |
215 /// The signature is based on non-comment tokens of the file outside | 225 /// The signature is based on non-comment tokens of the file outside |
216 /// of function bodies. | 226 /// of function bodies. |
217 List<int> _computeApiSignature(Token token) { | 227 void _computeSyntacticProperties(Token token) { |
218 var parser = new _BodySkippingParser(); | 228 var parser = new _BodySkippingParser(); |
219 parser.parseUnit(token); | 229 parser.parseUnit(token); |
220 | 230 |
| 231 _hasMixinApplication = parser.hasMixin; |
| 232 |
221 ApiSignature apiSignature = new ApiSignature(); | 233 ApiSignature apiSignature = new ApiSignature(); |
222 apiSignature.addBytes(_fsState._salt); | 234 apiSignature.addBytes(_fsState._salt); |
223 | 235 |
224 // Iterate over tokens and skip bodies. | 236 // Iterate over tokens and skip bodies. |
225 Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator; | 237 Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator; |
226 bodyIterator.moveNext(); | 238 bodyIterator.moveNext(); |
227 for (; token.kind != EOF_TOKEN; token = token.next) { | 239 for (; token.kind != EOF_TOKEN; token = token.next) { |
228 // Move to the body range that ends after the token. | 240 // Move to the body range that ends after the token. |
229 while (bodyIterator.current != null && | 241 while (bodyIterator.current != null && |
230 bodyIterator.current.last < token.charOffset) { | 242 bodyIterator.current.last < token.charOffset) { |
231 bodyIterator.moveNext(); | 243 bodyIterator.moveNext(); |
232 } | 244 } |
233 // If the current body range starts before or at the token, skip it. | 245 // If the current body range starts before or at the token, skip it. |
234 if (bodyIterator.current != null && | 246 if (bodyIterator.current != null && |
235 bodyIterator.current.first <= token.charOffset) { | 247 bodyIterator.current.first <= token.charOffset) { |
236 continue; | 248 continue; |
237 } | 249 } |
238 // The token is outside of a function body, add it. | 250 // The token is outside of a function body, add it. |
239 apiSignature.addString(token.lexeme); | 251 apiSignature.addString(token.lexeme); |
240 } | 252 } |
241 | 253 |
242 return apiSignature.toByteList(); | 254 // Store the API signature. |
| 255 _apiSignature = apiSignature.toByteList(); |
243 } | 256 } |
244 | 257 |
245 /// Exclude all `native 'xyz';` token sequences. | 258 /// Exclude all `native 'xyz';` token sequences. |
246 void _excludeNativeClauses(Token token) { | 259 void _excludeNativeClauses(Token token) { |
247 for (; token.kind != EOF_TOKEN; token = token.next) { | 260 for (; token.kind != EOF_TOKEN; token = token.next) { |
248 if (optional('native', token) && | 261 if (optional('native', token) && |
249 token.next.kind == STRING_TOKEN && | 262 token.next.kind == STRING_TOKEN && |
250 optional(';', token.next.next)) { | 263 optional(';', token.next.next)) { |
251 token.previous.next = token.next.next; | 264 token.previous.next = token.next.next; |
252 } | 265 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 final int last; | 445 final int last; |
433 | 446 |
434 _BodyRange(this.first, this.last); | 447 _BodyRange(this.first, this.last); |
435 | 448 |
436 @override | 449 @override |
437 String toString() => '[$first, $last]'; | 450 String toString() => '[$first, $last]'; |
438 } | 451 } |
439 | 452 |
440 /// The [Parser] that skips function bodies and remembers their token ranges. | 453 /// The [Parser] that skips function bodies and remembers their token ranges. |
441 class _BodySkippingParser extends Parser { | 454 class _BodySkippingParser extends Parser { |
| 455 bool hasMixin = false; |
442 final List<_BodyRange> bodyRanges = []; | 456 final List<_BodyRange> bodyRanges = []; |
443 | 457 |
444 _BodySkippingParser() : super(new Listener()); | 458 _BodySkippingParser() : super(new Listener()); |
445 | 459 |
446 @override | 460 @override |
447 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | 461 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
448 if (identical('{', token.lexeme)) { | 462 if (identical('{', token.lexeme)) { |
449 Token close = skipBlock(token); | 463 Token close = skipBlock(token); |
450 bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset)); | 464 bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset)); |
451 return close; | 465 return close; |
452 } | 466 } |
453 return super.parseFunctionBody(token, isExpression, allowAbstract); | 467 return super.parseFunctionBody(token, isExpression, allowAbstract); |
454 } | 468 } |
| 469 |
| 470 Token parseMixinApplication(Token token) { |
| 471 hasMixin = true; |
| 472 return super.parseMixinApplication(token); |
| 473 } |
455 } | 474 } |
456 | 475 |
457 /// [DirectiveListener] that skips native clauses. | 476 /// [DirectiveListener] that skips native clauses. |
458 class _DirectiveListenerWithNative extends DirectiveListener { | 477 class _DirectiveListenerWithNative extends DirectiveListener { |
459 @override | 478 @override |
460 Token handleNativeClause(Token token) => skipNativeClause(token); | 479 Token handleNativeClause(Token token) => skipNativeClause(token); |
461 } | 480 } |
462 | 481 |
463 /// [FileSystemState] based implementation of [FileSystem]. | 482 /// [FileSystemState] based implementation of [FileSystem]. |
464 /// It provides a consistent view on the known file system state. | 483 /// It provides a consistent view on the known file system state. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 node.isEvaluated = true; | 562 node.isEvaluated = true; |
544 cycle.libraries.add(node.file); | 563 cycle.libraries.add(node.file); |
545 } | 564 } |
546 topologicallySortedCycles.add(cycle); | 565 topologicallySortedCycles.add(cycle); |
547 } | 566 } |
548 | 567 |
549 _LibraryNode getNode(FileState file) { | 568 _LibraryNode getNode(FileState file) { |
550 return nodesOfFiles.putIfAbsent(file, () => new _LibraryNode(this, file)); | 569 return nodesOfFiles.putIfAbsent(file, () => new _LibraryNode(this, file)); |
551 } | 570 } |
552 } | 571 } |
OLD | NEW |