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