| Index: pkg/analyzer/lib/src/generated/parser.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
|
| index 465cf56d717e2dc544dd319b01daa0d594b303b4..fc20dc5caa5f994ecef5eba7af91eac60cb05b48 100644
|
| --- a/pkg/analyzer/lib/src/generated/parser.dart
|
| +++ b/pkg/analyzer/lib/src/generated/parser.dart
|
| @@ -1163,60 +1163,69 @@ class IncrementalParser {
|
| }
|
|
|
| /**
|
| - * Given a range of tokens that were re-scanned, re-parse the minimimum number of tokens to
|
| - * produce a consistent AST structure. The range is represented by the first and last tokens in
|
| - * the range. The tokens are assumed to be contained in the same token stream.
|
| - *
|
| - * @param firstToken the first token in the range of tokens that were re-scanned or `null`
|
| - * if no new tokens were inserted
|
| - * @param lastToken the last token in the range of tokens that were re-scanned or `null` if
|
| - * no new tokens were inserted
|
| + * Given a range of tokens that were re-scanned, re-parse the minimum number of tokens to produce
|
| + * a consistent AST structure. The range is represented by the first and last tokens in the range.
|
| + * The tokens are assumed to be contained in the same token stream.
|
| + *
|
| + * @param leftToken the token in the new token stream immediately to the left of the range of
|
| + * tokens that were inserted
|
| + * @param rightToken the token in the new token stream immediately to the right of the range of
|
| + * tokens that were inserted
|
| * @param originalStart the offset in the original source of the first character that was modified
|
| * @param originalEnd the offset in the original source of the last character that was modified
|
| */
|
| - ASTNode reparse(ASTNode originalStructure, Token firstToken, Token lastToken, int originalStart, int originalEnd) {
|
| + ASTNode reparse(ASTNode originalStructure, Token leftToken, Token rightToken, int originalStart, int originalEnd) {
|
| ASTNode oldNode = null;
|
| ASTNode newNode = null;
|
| - if (firstToken != null) {
|
| - if (originalEnd < originalStart) {
|
| - oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructure);
|
| - } else {
|
| - oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(originalStructure);
|
| - }
|
| - int originalOffset = oldNode.offset;
|
| - Token parseToken = findTokenAt(firstToken, originalOffset);
|
| - if (parseToken == null) {
|
| - return null;
|
| + Token firstToken = leftToken.next;
|
| + if (identical(firstToken, rightToken)) {
|
| + firstToken = leftToken;
|
| + }
|
| + if (originalEnd < originalStart) {
|
| + oldNode = new NodeLocator.con1(originalStart).searchWithin(originalStructure);
|
| + } else {
|
| + oldNode = new NodeLocator.con2(originalStart, originalEnd).searchWithin(originalStructure);
|
| + }
|
| + int originalOffset = oldNode.offset;
|
| + Token parseToken = findTokenAt(firstToken, originalOffset);
|
| + if (parseToken == null) {
|
| + return null;
|
| + }
|
| + Parser parser = new Parser(_source, _errorListener);
|
| + parser.currentToken = parseToken;
|
| + while (newNode == null) {
|
| + ASTNode parent = oldNode.parent;
|
| + if (parent == null) {
|
| + parseToken = findFirstToken(parseToken);
|
| + parser.currentToken = parseToken;
|
| + return parser.parseCompilationUnit2() as ASTNode;
|
| }
|
| - Parser parser = new Parser(_source, _errorListener);
|
| - parser.currentToken = parseToken;
|
| - while (newNode == null) {
|
| - ASTNode parent = oldNode.parent;
|
| - if (parent == null) {
|
| - parseToken = findFirstToken(parseToken);
|
| - parser.currentToken = parseToken;
|
| - return parser.parseCompilationUnit2() as ASTNode;
|
| - }
|
| - try {
|
| - IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(parser, oldNode);
|
| - newNode = parent.accept(dispatcher);
|
| - } on InsufficientContextException catch (exception) {
|
| - oldNode = parent;
|
| - originalOffset = oldNode.offset;
|
| - parseToken = findTokenAt(parseToken, originalOffset);
|
| - parser.currentToken = parseToken;
|
| - } on JavaException catch (exception) {
|
| - return null;
|
| + bool advanceToParent = false;
|
| + try {
|
| + IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(parser, oldNode);
|
| + newNode = parent.accept(dispatcher);
|
| + Token mappedToken = _tokenMap.get(oldNode.endToken.next);
|
| + if (mappedToken == null || mappedToken.offset != newNode.endToken.next.offset || newNode.offset != oldNode.offset) {
|
| + advanceToParent = true;
|
| }
|
| - }
|
| - if (newNode.offset != originalOffset) {
|
| + } on InsufficientContextException catch (exception) {
|
| + advanceToParent = true;
|
| + } on JavaException catch (exception) {
|
| return null;
|
| }
|
| - if (identical(oldNode, originalStructure)) {
|
| - return newNode as ASTNode;
|
| + if (advanceToParent) {
|
| + newNode = null;
|
| + oldNode = parent;
|
| + originalOffset = oldNode.offset;
|
| + parseToken = findTokenAt(parseToken, originalOffset);
|
| + parser.currentToken = parseToken;
|
| }
|
| + }
|
| + if (identical(oldNode, originalStructure)) {
|
| ResolutionCopier.copyResolutionData(oldNode, newNode);
|
| + return newNode as ASTNode;
|
| }
|
| + ResolutionCopier.copyResolutionData(oldNode, newNode);
|
| IncrementalASTCloner cloner = new IncrementalASTCloner(oldNode, newNode, _tokenMap);
|
| return originalStructure.accept(cloner) as ASTNode;
|
| }
|
| @@ -1342,9 +1351,7 @@ class Parser {
|
| InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.Parser.parseCompilationUnit");
|
| try {
|
| _currentToken = token;
|
| - CompilationUnit compilationUnit = parseCompilationUnit2();
|
| - gatherTodoComments(token);
|
| - return compilationUnit;
|
| + return parseCompilationUnit2();
|
| } finally {
|
| instrumentation.log2(2);
|
| }
|
| @@ -1722,8 +1729,9 @@ class Parser {
|
| if (partOfDirectiveFound) {
|
| reportError9(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, []);
|
| } else {
|
| - for (Directive precedingDirective in directives) {
|
| - reportError10(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, precedingDirective.keyword, []);
|
| + int directiveCount = directives.length;
|
| + for (int i = 0; i < directiveCount; i++) {
|
| + reportError10(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, directives[i].keyword, []);
|
| }
|
| partOfDirectiveFound = true;
|
| }
|
| @@ -2529,7 +2537,15 @@ class Parser {
|
| *
|
| * @return the synthetic identifier that was created
|
| */
|
| - SimpleIdentifier createSyntheticIdentifier() => new SimpleIdentifier.full(createSyntheticToken2(TokenType.IDENTIFIER));
|
| + SimpleIdentifier createSyntheticIdentifier() {
|
| + Token syntheticToken;
|
| + if (identical(_currentToken.type, TokenType.KEYWORD)) {
|
| + syntheticToken = injectToken(new SyntheticStringToken(TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
|
| + } else {
|
| + syntheticToken = createSyntheticToken2(TokenType.IDENTIFIER);
|
| + }
|
| + return new SimpleIdentifier.full(syntheticToken);
|
| + }
|
|
|
| /**
|
| * Create a synthetic string literal.
|
| @@ -2543,14 +2559,14 @@ class Parser {
|
| *
|
| * @return the synthetic token that was created
|
| */
|
| - Token createSyntheticToken(Keyword keyword) => new Parser_SyntheticKeywordToken(keyword, _currentToken.offset);
|
| + Token createSyntheticToken(Keyword keyword) => injectToken(new Parser_SyntheticKeywordToken(keyword, _currentToken.offset));
|
|
|
| /**
|
| * Create a synthetic token with the given type.
|
| *
|
| * @return the synthetic token that was created
|
| */
|
| - Token createSyntheticToken2(TokenType type) => new StringToken(type, "", _currentToken.offset);
|
| + Token createSyntheticToken2(TokenType type) => injectToken(new StringToken(type, "", _currentToken.offset));
|
|
|
| /**
|
| * Check that the given expression is assignable and report an error if it isn't.
|
| @@ -2617,7 +2633,9 @@ class Parser {
|
| * @return the range that was found
|
| */
|
| List<int> findRange(List<List<int>> ranges, int index) {
|
| - for (List<int> range in ranges) {
|
| + int rangeCount = ranges.length;
|
| + for (int i = 0; i < rangeCount; i++) {
|
| + List<int> range = ranges[i];
|
| if (range[0] <= index && index <= range[1]) {
|
| return range;
|
| } else if (index < range[0]) {
|
| @@ -2627,19 +2645,6 @@ class Parser {
|
| return null;
|
| }
|
|
|
| - void gatherTodoComments(Token token) {
|
| - while (token != null && token.type != TokenType.EOF) {
|
| - Token commentToken = token.precedingComments;
|
| - while (commentToken != null) {
|
| - if (identical(commentToken.type, TokenType.SINGLE_LINE_COMMENT) || identical(commentToken.type, TokenType.MULTI_LINE_COMMENT)) {
|
| - scrapeTodoComment(commentToken);
|
| - }
|
| - commentToken = commentToken.next;
|
| - }
|
| - token = token.next;
|
| - }
|
| - }
|
| -
|
| /**
|
| * Advance to the next token in the token stream, making it the new current token.
|
| *
|
| @@ -2726,6 +2731,19 @@ class Parser {
|
| }
|
|
|
| /**
|
| + * Inject the given token into the token stream immediately before the current token.
|
| + *
|
| + * @param token the token to be added to the token stream
|
| + * @return the token that was just added to the token stream
|
| + */
|
| + Token injectToken(Token token) {
|
| + Token previous = _currentToken.previous;
|
| + token.setNext(_currentToken);
|
| + previous.setNext(token);
|
| + return token;
|
| + }
|
| +
|
| + /**
|
| * Return `true` if the current token appears to be the beginning of a function declaration.
|
| *
|
| * @return `true` if the current token appears to be the beginning of a function declaration
|
| @@ -3623,12 +3641,11 @@ class Parser {
|
| return null;
|
| }
|
| try {
|
| - List<bool> errorFound = [false];
|
| - AnalysisErrorListener listener = new AnalysisErrorListener_16(errorFound);
|
| + BooleanErrorListener listener = new BooleanErrorListener();
|
| Scanner scanner = new Scanner(null, new SubSequenceReader(new CharSequence(referenceSource), sourceOffset), listener);
|
| scanner.setSourceStart(1, 1);
|
| Token firstToken = scanner.tokenize();
|
| - if (errorFound[0]) {
|
| + if (listener.errorReported) {
|
| return null;
|
| }
|
| Token newKeyword = null;
|
| @@ -3869,7 +3886,7 @@ class Parser {
|
| }
|
| } else {
|
| body = parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
|
| - if (constKeyword != null && factoryKeyword != null) {
|
| + if (constKeyword != null && factoryKeyword != null && externalKeyword == null) {
|
| reportError10(ParserErrorCode.CONST_FACTORY, factoryKeyword, []);
|
| } else if (body is EmptyFunctionBody) {
|
| if (factoryKeyword != null && externalKeyword == null) {
|
| @@ -5577,7 +5594,7 @@ class Parser {
|
| if (definedLabels.contains(label)) {
|
| reportError10(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, identifier.token, [label]);
|
| } else {
|
| - javaSetAdd(definedLabels, label);
|
| + definedLabels.add(label);
|
| }
|
| Token colon = expect2(TokenType.COLON);
|
| labels.add(new Label.full(identifier, colon));
|
| @@ -6032,20 +6049,6 @@ class Parser {
|
| }
|
|
|
| /**
|
| - * Look for user defined tasks in comments and convert them into info level analysis issues.
|
| - *
|
| - * @param commentToken the comment token to analyze
|
| - */
|
| - void scrapeTodoComment(Token commentToken) {
|
| - JavaPatternMatcher matcher = new JavaPatternMatcher(TodoCode.TODO_REGEX, commentToken.lexeme);
|
| - if (matcher.find()) {
|
| - int offset = commentToken.offset + matcher.start() + matcher.group(1).length;
|
| - int length = matcher.group(2).length;
|
| - // _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)]));
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the
|
| * given token, without actually creating a type or changing the current token. Return the token
|
| * following the type that was parsed, or `null` if the given token is not the first token
|
| @@ -6843,16 +6846,6 @@ class Parser_SyntheticKeywordToken extends KeywordToken {
|
| int get length => 0;
|
| }
|
|
|
| -class AnalysisErrorListener_16 implements AnalysisErrorListener {
|
| - List<bool> errorFound;
|
| -
|
| - AnalysisErrorListener_16(this.errorFound);
|
| -
|
| - void onError(AnalysisError error) {
|
| - errorFound[0] = true;
|
| - }
|
| -}
|
| -
|
| /**
|
| * The enumeration `ParserErrorCode` defines the error codes used for errors detected by the
|
| * parser. The convention for this class is for the name of the error code to indicate the problem
|
|
|