Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Unified Diff: pkg/analyzer/lib/src/generated/incremental_scanner.dart

Issue 745873002: Stop copying tokens in incremental scanner (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Clean-up Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/incremental_scanner.dart
diff --git a/pkg/analyzer/lib/src/generated/incremental_scanner.dart b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
index 75df98d49fa204d02355d6b7f291d19d98178576..04072bcbdfd3a5b68bbf66d79478112e1f4f4b3a 100644
--- a/pkg/analyzer/lib/src/generated/incremental_scanner.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
@@ -12,14 +12,28 @@ import 'source.dart';
import 'utilities_collection.dart' show TokenMap;
/**
- * Instances of the class `IncrementalScanner` implement a scanner that scans a subset of a
- * string and inserts the resulting tokens into the middle of an existing token stream.
+ * An `IncrementalScanner` is a scanner that scans a subset of a string and
+ * inserts the resulting tokens into the middle of an existing token stream.
*/
-class IncrementalScanner extends Scanner {
+class IncrementalScanner {
+ /**
+ * The source being scanned.
+ */
+ final Source source;
+
/**
* The reader used to access the characters in the source.
*/
- CharacterReader _reader;
+ final CharacterReader reader;
+
+ /**
+ * The error listener that will be informed of any errors that are found
+ * during the scan.
+ *
+ * TODO(brianwilkerson) Replace this with a list of errors so that we can
+ * update the errors.
+ */
+ final AnalysisErrorListener errorListener;
/**
* A map from tokens that were copied to the copies of the tokens.
@@ -46,17 +60,11 @@ class IncrementalScanner extends Scanner {
bool _hasNonWhitespaceChange = false;
/**
- * Initialize a newly created scanner.
- *
- * @param source the source being scanned
- * @param reader the character reader used to read the characters in the source
- * @param errorListener the error listener that will be informed of any errors that are found
- */
- IncrementalScanner(Source source, CharacterReader reader,
- AnalysisErrorListener errorListener)
- : super(source, reader, errorListener) {
- this._reader = reader;
- }
+ * Initialize a newly created scanner to scan characters within the given
+ * [source]. The content of the source can be read using the given [reader].
+ * Any errors that are found will be reported to the given [errorListener].
+ */
+ IncrementalScanner(this.source, this.reader, this.errorListener);
/**
* Return `true` if there were any tokens either added or removed (or both) as a result of
@@ -92,97 +100,87 @@ class IncrementalScanner extends Scanner {
TokenMap get tokenMap => _tokenMap;
/**
- * Given the stream of tokens scanned from the original source, the modified source (the result of
- * replacing one contiguous range of characters with another string of characters), and a
- * specification of the modification that was made, return a stream of tokens scanned from the
- * modified source. The original stream of tokens will not be modified.
+ * Given the [stream] of tokens scanned from the original source, the modified
+ * source (the result of replacing one contiguous range of characters with
+ * another string of characters), and a specification of the modification that
+ * was made, update the token stream to reflect the modified source. Return
+ * the first token in the updated token stream.
*
- * @param originalStream the stream of tokens scanned from the original source
- * @param index the index of the first character in both the original and modified source that was
- * affected by the modification
- * @param removedLength the number of characters removed from the original source
- * @param insertedLength the number of characters added to the modified source
- */
- Token rescan(Token originalStream, int index, int removedLength,
- int insertedLength) {
- //
- // Copy all of the tokens in the originalStream whose end is less than the
- // replacement start. (If the replacement start is equal to the end of an
- // existing token, then it means that the existing token might have been
- // modified, so we need to rescan it.)
- //
- while (originalStream.type != TokenType.EOF && originalStream.end < index) {
- originalStream = _copyAndAdvance(originalStream, 0);
+ * The [stream] is expected to be the first non-EOF token in the token stream.
+ *
+ * The modification is specified by the [index] of the first character in both
+ * the original and modified source that was affected by the modification, the
+ * number of characters removed from the original source (the [removedLength])
+ * and the number of characters added to the modified source (the
+ * [insertedLength]).
+ */
+ Token rescan(Token stream, int index, int removedLength, int insertedLength) {
+ Token leftEof = stream.previous;
+ //
+ // Compute the delta between the character index of characters after the
+ // modified region in the original source and the index of the corresponding
+ // character in the modified source.
+ //
+ int delta = insertedLength - removedLength;
+ //
+ // Skip past the tokens whose end is less than the replacement start. (If
+ // the replacement start is equal to the end of an existing token, then it
+ // means that the existing token might have been modified, so we need to
+ // rescan it.)
+ //
+ while (stream.type != TokenType.EOF && stream.end < index) {
+ _tokenMap.put(stream, stream);
+ stream = stream.next;
}
- Token oldFirst = originalStream;
- Token oldLeftToken = originalStream.previous;
- _leftToken = tail;
+ Token oldFirst = stream;
+ Token oldLeftToken = stream.previous;
+ _leftToken = oldLeftToken;
//
- // Skip tokens in the original stream until we find a token whose offset is
- // greater than the end of the removed region. (If the end of the removed
- // region is equal to the beginning of an existing token, then it means that
- // the existing token might have been modified, so we need to rescan it.)
+ // Skip past tokens until we find a token whose offset is greater than the
+ // end of the removed region. (If the end of the removed region is equal to
+ // the beginning of an existing token, then it means that the existing token
+ // might have been modified, so we need to rescan it.)
//
int removedEnd = index + (removedLength == 0 ? 0 : removedLength - 1);
- while (originalStream.type != TokenType.EOF &&
- originalStream.offset <= removedEnd) {
- originalStream = originalStream.next;
+ while (stream.type != TokenType.EOF && stream.offset <= removedEnd) {
+ stream = stream.next;
}
+ //
+ // Figure out which region of characters actually needs to be re-scanned.
+ //
Token oldLast;
Token oldRightToken;
- if (originalStream.type != TokenType.EOF &&
- removedEnd + 1 == originalStream.offset) {
- oldLast = originalStream;
- originalStream = originalStream.next;
- oldRightToken = originalStream;
+ if (stream.type != TokenType.EOF && removedEnd + 1 == stream.offset) {
+ oldLast = stream;
+ stream = stream.next;
+ oldRightToken = stream;
} else {
- oldLast = originalStream.previous;
- oldRightToken = originalStream;
+ oldLast = stream.previous;
+ oldRightToken = stream;
}
//
- // Compute the delta between the character index of characters after the
- // modified region in the original source and the index of the corresponding
- // character in the modified source.
- //
- int delta = insertedLength - removedLength;
- //
// Compute the range of characters that are known to need to be rescanned.
// If the index is within an existing token, then we need to start at the
// beginning of the token.
//
- int scanStart = math.min(oldFirst.offset, index);
- int oldEnd = oldLast.end + delta - 1;
- int newEnd = index + insertedLength - 1;
- int scanEnd = math.max(newEnd, oldEnd);
- //
- // Starting at the start of the scan region, scan tokens from the
- // modifiedSource until the end of the just scanned token is greater than or
- // equal to end of the scan region in the modified source. Include trailing
- // characters of any token that was split as a result of inserted text,
- // as in "ab" --> "a.b".
- //
- _reader.offset = scanStart - 1;
- int next = _reader.advance();
- while (next != -1 && _reader.offset <= scanEnd) {
- next = bigSwitch(next);
- }
+ int scanStart = math.max(oldFirst.previous.end, 0);
+ int scanEnd = oldLast.end + delta;
//
- // Copy the remaining tokens in the original stream, but apply the delta to
- // the token's offset.
+ // Starting at the start of the scan region, scan tokens from the modified
+ // source until the end of the just scanned token is greater than or equal
+ // to end of the scan region in the modified source. Include trailing
+ // characters of any token that was split as a result of inserted text, as
+ // in "ab" --> "a.b".
//
- if (originalStream.type == TokenType.EOF) {
- _copyAndAdvance(originalStream, delta);
- _rightToken = tail;
- _rightToken.setNextWithoutSettingPrevious(_rightToken);
- } else {
- originalStream = _copyAndAdvance(originalStream, delta);
- _rightToken = tail;
- while (originalStream.type != TokenType.EOF) {
- originalStream = _copyAndAdvance(originalStream, delta);
- }
- Token eof = _copyAndAdvance(originalStream, delta);
- eof.setNextWithoutSettingPrevious(eof);
- }
+ Token replacementStart = _scanRange(scanStart, scanEnd);
+ oldLeftToken.setNext(replacementStart);
+ Token replacementEnd = _findEof(replacementStart).previous;
+ replacementEnd.setNext(stream);
+ //
+ // Apply the delta to the tokens after the last new token.
+ //
+ _updateOffsets(stream, delta);
+ _rightToken = stream;
//
// If the index is immediately after an existing token and the inserted
// characters did not change that original token, then adjust the leftToken
@@ -221,22 +219,7 @@ class IncrementalScanner extends Scanner {
// parsing.
// TODO(brianwilkerson) Update the lineInfo.
//
- return firstToken;
- }
-
- Token _copyAndAdvance(Token originalToken, int delta) {
- Token copiedToken = originalToken.copy();
- _tokenMap.put(originalToken, copiedToken);
- copiedToken.offset += delta;
- appendToken(copiedToken);
- Token originalComment = originalToken.precedingComments;
- Token copiedComment = originalToken.precedingComments;
- while (originalComment != null) {
- _tokenMap.put(originalComment, copiedComment);
- originalComment = originalComment.next;
- copiedComment = copiedComment.next;
- }
- return originalToken.next;
+ return leftEof.next;
}
/**
@@ -251,4 +234,45 @@ class IncrementalScanner extends Scanner {
oldToken.type == newToken.type &&
oldToken.length == newToken.length &&
oldToken.lexeme == newToken.lexeme;
+
+ /**
+ * Given a [token], return the EOF token that follows the token.
+ */
+ Token _findEof(Token token) {
+ while (token.type != TokenType.EOF) {
+ token = token.next;
+ }
+ return token;
+ }
+
+ /**
+ * Scan the token between the [start] (inclusive) and [end] (exclusive)
+ * offsets.
+ */
+ Token _scanRange(int start, int end) {
+ Scanner scanner = new Scanner(
+ source,
+ new CharacterRangeReader(reader, start, end),
+ errorListener);
+ return scanner.tokenize();
+ }
+
+ /**
+ * Update the offsets of every token from the given [token] to the end of the
+ * stream by adding the given [delta].
+ */
+ void _updateOffsets(Token token, int delta) {
+ while (token.type != TokenType.EOF) {
+ _tokenMap.put(token, token);
+ token.offset += delta;
+ Token comment = token.precedingComments;
+ while (comment != null) {
+ comment.offset += delta;
+ comment = comment.next;
+ }
+ token = token.next;
+ }
+ _tokenMap.put(token, token);
+ token.offset += delta;
Paul Berry 2014/11/20 22:41:59 Does the EOF token ever have precedingComments? (
Brian Wilkerson 2014/11/20 22:55:02 Yes, when there are comments at the end of the fil
+ }
}
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698