Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:typed_data'; | |
| 6 | |
| 7 import 'package:front_end/src/base/api_signature.dart'; | |
| 8 import 'package:front_end/src/fasta/parser/listener.dart' show Listener; | |
| 9 import 'package:front_end/src/fasta/parser/parser.dart' show Parser, optional; | |
| 10 import 'package:front_end/src/fasta/parser/top_level_parser.dart'; | |
| 11 import 'package:front_end/src/fasta/scanner.dart'; | |
| 12 import 'package:front_end/src/fasta/scanner/token_constants.dart' | |
| 13 show STRING_TOKEN; | |
| 14 import 'package:front_end/src/fasta/source/directive_listener.dart'; | |
| 15 import 'package:front_end/src/incremental/format.dart'; | |
| 16 | |
| 17 /// Compute the [UnlinkedUnitBuilder] for the [content]. | |
| 18 UnlinkedUnitBuilder computeUnlinkedUnit(List<int> salt, List<int> content) { | |
| 19 // Scan the content. | |
| 20 ScannerResult scanResult = _scan(content); | |
| 21 Token token = scanResult.tokens; | |
| 22 | |
| 23 // Parse directives. | |
| 24 var listener = new DirectiveListener(); | |
| 25 new TopLevelParser(listener).parseUnit(token); | |
|
Paul Berry
2017/06/13 21:49:46
It seems wasteful that we call `parseUnit` here an
scheglov
2017/06/13 22:03:21
Well, yes, we waste something. But in general TopL
| |
| 26 | |
| 27 // Parse to record function bodies. | |
| 28 var parser = new _BodySkippingParser(); | |
| 29 parser.parseUnit(token); | |
| 30 | |
| 31 ApiSignature apiSignature = new ApiSignature(); | |
| 32 apiSignature.addBytes(salt); | |
| 33 | |
| 34 // Iterate over tokens and skip bodies. | |
| 35 Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator; | |
| 36 bodyIterator.moveNext(); | |
| 37 for (; token.kind != EOF_TOKEN; token = token.next) { | |
| 38 // Move to the body range that ends after the token. | |
| 39 while (bodyIterator.current != null && | |
| 40 bodyIterator.current.last < token.charOffset) { | |
| 41 bodyIterator.moveNext(); | |
| 42 } | |
| 43 // If the current body range starts before or at the token, skip it. | |
| 44 if (bodyIterator.current != null && | |
| 45 bodyIterator.current.first <= token.charOffset) { | |
| 46 continue; | |
| 47 } | |
| 48 // The token is outside of a function body, add it. | |
| 49 apiSignature.addString(token.lexeme); | |
| 50 } | |
| 51 | |
| 52 return new UnlinkedUnitBuilder( | |
| 53 apiSignature: apiSignature.toByteList(), | |
| 54 imports: listener.imports.map(_toUnlinkedNamespaceDirective).toList(), | |
| 55 exports: listener.exports.map(_toUnlinkedNamespaceDirective).toList(), | |
| 56 parts: listener.parts.toList(), | |
| 57 hasMixinApplication: parser.hasMixin); | |
| 58 } | |
| 59 | |
| 60 /// Exclude all `native 'xyz';` token sequences. | |
| 61 void _excludeNativeClauses(Token token) { | |
|
Paul Berry
2017/06/13 21:49:46
This seems like an unnecessarily fragile hack. Ca
scheglov
2017/06/13 22:03:21
Unfortunately my understanding is that position of
Paul Berry
2017/06/14 12:20:52
Ok, I will have a discussion with Peter about this
Siggi Cherem (dart-lang)
2017/06/14 22:37:38
FWIW - in our perf scripts we take the other appro
scheglov
2017/06/14 23:20:34
OK, I see how this is done for parsing directives.
| |
| 62 for (; token.kind != EOF_TOKEN; token = token.next) { | |
| 63 if (optional('native', token) && | |
| 64 token.next.kind == STRING_TOKEN && | |
| 65 optional(';', token.next.next)) { | |
| 66 token.previous.next = token.next.next; | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 /// Scan the content of the file. | |
| 72 ScannerResult _scan(List<int> content) { | |
| 73 var zeroTerminatedBytes = new Uint8List(content.length + 1); | |
| 74 zeroTerminatedBytes.setRange(0, content.length, content); | |
| 75 ScannerResult result = scan(zeroTerminatedBytes); | |
| 76 _excludeNativeClauses(result.tokens); | |
| 77 return result; | |
| 78 } | |
| 79 | |
| 80 /// Convert [NamespaceCombinator] into [UnlinkedCombinatorBuilder]. | |
| 81 UnlinkedCombinatorBuilder _toUnlinkedCombinator(NamespaceCombinator c) => | |
| 82 new UnlinkedCombinatorBuilder(isShow: c.isShow, names: c.names.toList()); | |
| 83 | |
| 84 /// Convert [NamespaceDirective] into [UnlinkedNamespaceDirectiveBuilder]. | |
| 85 UnlinkedNamespaceDirectiveBuilder _toUnlinkedNamespaceDirective( | |
| 86 NamespaceDirective directive) => | |
| 87 new UnlinkedNamespaceDirectiveBuilder( | |
| 88 uri: directive.uri, | |
| 89 combinators: directive.combinators.map(_toUnlinkedCombinator).toList()); | |
| 90 | |
| 91 /// The char range of a function body. | |
| 92 class _BodyRange { | |
| 93 /// The char offset of the first token in the range. | |
| 94 final int first; | |
| 95 | |
| 96 /// The char offset of the last token in the range. | |
| 97 final int last; | |
| 98 | |
| 99 _BodyRange(this.first, this.last); | |
| 100 | |
| 101 @override | |
| 102 String toString() => '[$first, $last]'; | |
| 103 } | |
| 104 | |
| 105 /// The [Parser] that skips function bodies and remembers their token ranges. | |
| 106 class _BodySkippingParser extends Parser { | |
| 107 bool hasMixin = false; | |
| 108 final List<_BodyRange> bodyRanges = []; | |
| 109 | |
| 110 _BodySkippingParser() : super(new Listener()); | |
| 111 | |
| 112 @override | |
| 113 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | |
|
ahe
2017/08/07 14:05:13
This feature is already provided by ClassMemberPar
| |
| 114 if (identical('{', token.lexeme)) { | |
| 115 Token close = skipBlock(token); | |
| 116 bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset)); | |
| 117 return close; | |
| 118 } | |
| 119 return super.parseFunctionBody(token, isExpression, allowAbstract); | |
| 120 } | |
| 121 | |
| 122 Token parseMixinApplication(Token token) { | |
|
ahe
2017/08/07 14:05:13
You should be able to collect this information via
| |
| 123 hasMixin = true; | |
| 124 return super.parseMixinApplication(token); | |
| 125 } | |
| 126 } | |
| OLD | NEW |