Index: pkg/front_end/lib/src/incremental/file_state.dart |
diff --git a/pkg/front_end/lib/src/incremental/file_state.dart b/pkg/front_end/lib/src/incremental/file_state.dart |
index c4882b5f328c40b409b6912fdd6b61fa736d2ab1..77f4d147e9e0bef8a2fc845c5f2eae8eff67cb6f 100644 |
--- a/pkg/front_end/lib/src/incremental/file_state.dart |
+++ b/pkg/front_end/lib/src/incremental/file_state.dart |
@@ -5,20 +5,15 @@ |
import 'dart:async'; |
import 'dart:typed_data'; |
+import 'package:convert/convert.dart'; |
import 'package:crypto/crypto.dart'; |
import 'package:front_end/file_system.dart'; |
-import 'package:front_end/src/base/api_signature.dart'; |
import 'package:front_end/src/base/resolve_relative_uri.dart'; |
import 'package:front_end/src/dependency_walker.dart' as graph; |
-import 'package:front_end/src/fasta/parser/dart_vm_native.dart'; |
-import 'package:front_end/src/fasta/parser/listener.dart' show Listener; |
-import 'package:front_end/src/fasta/parser/parser.dart' show Parser, optional; |
-import 'package:front_end/src/fasta/parser/top_level_parser.dart'; |
-import 'package:front_end/src/fasta/scanner.dart'; |
-import 'package:front_end/src/fasta/scanner/token_constants.dart' |
- show STRING_TOKEN; |
-import 'package:front_end/src/fasta/source/directive_listener.dart'; |
import 'package:front_end/src/fasta/translate_uri.dart'; |
+import 'package:front_end/src/incremental/byte_store.dart'; |
+import 'package:front_end/src/incremental/format.dart'; |
+import 'package:front_end/src/incremental/unlinked_unit.dart'; |
import 'package:kernel/target/vm.dart'; |
/// This function is called for each newly discovered file, and the returned |
@@ -145,15 +140,22 @@ class FileState { |
// Compute the content hash. |
_contentHash = md5.convert(_content).bytes; |
- // Scan the content. |
- ScannerResult scanResult = _scan(); |
- |
- // Compute syntactic properties. |
- _computeSyntacticProperties(scanResult.tokens); |
+ // Prepare bytes of the unlinked unit - existing or new. |
+ List<int> unlinkedBytes; |
+ { |
+ String unlinkedKey = hex.encode(_contentHash) + '.unlinked'; |
+ unlinkedBytes = _fsState._byteStore.get(unlinkedKey); |
+ if (unlinkedBytes == null) { |
+ var builder = computeUnlinkedUnit(_fsState._salt, _content); |
+ unlinkedBytes = builder.toBytes(); |
+ _fsState._byteStore.put(unlinkedKey, unlinkedBytes); |
+ } |
+ } |
- // Parse directives. |
- var listener = new _DirectiveListenerWithNative(); |
- new TopLevelParser(listener).parseUnit(scanResult.tokens); |
+ // Read the unlinked unit. |
+ UnlinkedUnit unlinkedUnit = new UnlinkedUnit(unlinkedBytes); |
+ _apiSignature = unlinkedUnit.apiSignature; |
+ _hasMixinApplication = unlinkedUnit.hasMixinApplication; |
// Build the graph. |
_importedLibraries = <FileState>[]; |
@@ -167,22 +169,22 @@ class FileState { |
_importedLibraries.add(coreFile); |
} |
} |
- for (NamespaceDirective import_ in listener.imports) { |
+ for (var import_ in unlinkedUnit.imports) { |
FileState file = await _getFileForRelativeUri(import_.uri); |
if (file != null) { |
_importedLibraries.add(file); |
} |
} |
await _addVmTargetImportsForCore(); |
- for (NamespaceDirective export_ in listener.exports) { |
+ for (var export_ in unlinkedUnit.exports) { |
FileState file = await _getFileForRelativeUri(export_.uri); |
if (file != null) { |
_exportedLibraries.add(file); |
_exports.add(new NamespaceExport(file, export_.combinators)); |
} |
} |
- for (String uri in listener.parts) { |
- FileState file = await _getFileForRelativeUri(uri); |
+ for (var part_ in unlinkedUnit.parts) { |
+ FileState file = await _getFileForRelativeUri(part_); |
if (file != null) { |
_partFiles.add(file); |
} |
@@ -220,52 +222,6 @@ class FileState { |
} |
} |
- /// Compute syntactic properties of the file: [_apiSignature] and [_hasMixinApplication]. |
- /// |
- /// The signature is based on non-comment tokens of the file outside |
- /// of function bodies. |
- void _computeSyntacticProperties(Token token) { |
- var parser = new _BodySkippingParser(); |
- parser.parseUnit(token); |
- |
- _hasMixinApplication = parser.hasMixin; |
- |
- ApiSignature apiSignature = new ApiSignature(); |
- apiSignature.addBytes(_fsState._salt); |
- |
- // Iterate over tokens and skip bodies. |
- Iterator<_BodyRange> bodyIterator = parser.bodyRanges.iterator; |
- bodyIterator.moveNext(); |
- for (; token.kind != EOF_TOKEN; token = token.next) { |
- // Move to the body range that ends after the token. |
- while (bodyIterator.current != null && |
- bodyIterator.current.last < token.charOffset) { |
- bodyIterator.moveNext(); |
- } |
- // If the current body range starts before or at the token, skip it. |
- if (bodyIterator.current != null && |
- bodyIterator.current.first <= token.charOffset) { |
- continue; |
- } |
- // The token is outside of a function body, add it. |
- apiSignature.addString(token.lexeme); |
- } |
- |
- // Store the API signature. |
- _apiSignature = apiSignature.toByteList(); |
- } |
- |
- /// Exclude all `native 'xyz';` token sequences. |
- void _excludeNativeClauses(Token token) { |
- for (; token.kind != EOF_TOKEN; token = token.next) { |
- if (optional('native', token) && |
- token.next.kind == STRING_TOKEN && |
- optional(';', token.next.next)) { |
- token.previous.next = token.next.next; |
- } |
- } |
- } |
- |
/// Return the [FileState] for the given [relativeUri] or `null` if the URI |
/// cannot be parsed, cannot correspond any file, etc. |
Future<FileState> _getFileForRelativeUri(String relativeUri) async { |
@@ -284,19 +240,11 @@ class FileState { |
return await _fsState.getFile(absoluteUri); |
} |
- |
- /// Scan the content of the file. |
- ScannerResult _scan() { |
- var zeroTerminatedBytes = new Uint8List(_content.length + 1); |
- zeroTerminatedBytes.setRange(0, _content.length, _content); |
- ScannerResult result = scan(zeroTerminatedBytes); |
- _excludeNativeClauses(result.tokens); |
- return result; |
- } |
} |
/// Information about known file system state. |
class FileSystemState { |
+ final ByteStore _byteStore; |
final FileSystem fileSystem; |
final TranslateUri uriTranslator; |
final List<int> _salt; |
@@ -312,8 +260,8 @@ class FileSystemState { |
/// contain `file:*` URIs as keys. |
final Map<Uri, FileState> _fileUriToFile = {}; |
- FileSystemState( |
- this.fileSystem, this.uriTranslator, this._salt, this._newFileFn); |
+ FileSystemState(this._byteStore, this.fileSystem, this.uriTranslator, |
+ this._salt, this._newFileFn); |
/// Return the [FileSystem] that is backed by this [FileSystemState]. The |
/// files in this [FileSystem] always have the same content as the |
@@ -419,13 +367,13 @@ class LibraryCycle { |
/// Information about a single `export` directive. |
class NamespaceExport { |
final FileState library; |
- final List<NamespaceCombinator> combinators; |
+ final List<UnlinkedCombinator> combinators; |
NamespaceExport(this.library, this.combinators); |
/// Return `true` if the [name] satisfies the sequence of the [combinators]. |
bool isExposed(String name) { |
- for (NamespaceCombinator combinator in combinators) { |
+ for (var combinator in combinators) { |
if (combinator.isShow) { |
if (!combinator.names.contains(name)) { |
return false; |
@@ -440,49 +388,6 @@ class NamespaceExport { |
} |
} |
-/// The char range of a function body. |
-class _BodyRange { |
- /// The char offset of the first token in the range. |
- final int first; |
- |
- /// The char offset of the last token in the range. |
- final int last; |
- |
- _BodyRange(this.first, this.last); |
- |
- @override |
- String toString() => '[$first, $last]'; |
-} |
- |
-/// The [Parser] that skips function bodies and remembers their token ranges. |
-class _BodySkippingParser extends Parser { |
- bool hasMixin = false; |
- final List<_BodyRange> bodyRanges = []; |
- |
- _BodySkippingParser() : super(new Listener()); |
- |
- @override |
- Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { |
- if (identical('{', token.lexeme)) { |
- Token close = skipBlock(token); |
- bodyRanges.add(new _BodyRange(token.charOffset, close.charOffset)); |
- return close; |
- } |
- return super.parseFunctionBody(token, isExpression, allowAbstract); |
- } |
- |
- Token parseMixinApplication(Token token) { |
- hasMixin = true; |
- return super.parseMixinApplication(token); |
- } |
-} |
- |
-/// [DirectiveListener] that skips native clauses. |
-class _DirectiveListenerWithNative extends DirectiveListener { |
- @override |
- Token handleNativeClause(Token token) => skipNativeClause(token); |
-} |
- |
/// [FileSystemState] based implementation of [FileSystem]. |
/// It provides a consistent view on the known file system state. |
class _FileSystemView implements FileSystem { |