 Chromium Code Reviews
 Chromium Code Reviews Issue 3012663002:
  Mark unsafe token access in AstBuilder  (Closed)
    
  
    Issue 3012663002:
  Mark unsafe token access in AstBuilder  (Closed) 
  | Index: pkg/analyzer/lib/src/fasta/ast_builder.dart | 
| diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart | 
| index 6f7f95a97f69c147f2ee11a9bf26a21a1b8f60cf..8396f26ca1f006fdb6d0a3b7f023c1b172f09a74 100644 | 
| --- a/pkg/analyzer/lib/src/fasta/ast_builder.dart | 
| +++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart | 
| @@ -394,7 +394,8 @@ class AstBuilder extends ScopeListener { | 
| Statement elsePart = popIfNotNull(elseToken); | 
| Statement thenPart = pop(); | 
| Expression condition = pop(); | 
| - analyzer.BeginToken leftParenthesis = ifToken.next; | 
| + analyzer.BeginToken leftParenthesis = | 
| + unsafeToken(ifToken.next, TokenType.OPEN_PAREN); | 
| push(ast.ifStatement(ifToken, ifToken.next, condition, | 
| leftParenthesis.endGroup, thenPart, elseToken, elsePart)); | 
| } | 
| @@ -556,7 +557,8 @@ class AstBuilder extends ScopeListener { | 
| exitLocalScope(); | 
| exitContinueTarget(); | 
| exitBreakTarget(); | 
| - analyzer.BeginToken leftParenthesis = forKeyword.next; | 
| + analyzer.BeginToken leftParenthesis = | 
| + unsafeToken(forKeyword.next, TokenType.OPEN_PAREN); | 
| VariableDeclarationList variableList; | 
| Expression initializer; | 
| @@ -584,7 +586,7 @@ class AstBuilder extends ScopeListener { | 
| condition, | 
| rightSeparator, | 
| updates, | 
| - leftParenthesis.endGroup, | 
| + leftParenthesis?.endGroup, | 
| body)); | 
| } | 
| @@ -846,7 +848,7 @@ class AstBuilder extends ScopeListener { | 
| covariantKeyword: covariantKeyword, | 
| type: typeOrFunctionTypedParameter.returnType, | 
| thisKeyword: thisKeyword, | 
| - period: thisKeyword.next, | 
| + period: unsafeToken(thisKeyword.next, TokenType.PERIOD), | 
| typeParameters: typeOrFunctionTypedParameter.typeParameters, | 
| parameters: typeOrFunctionTypedParameter.parameters); | 
| } | 
| @@ -1060,6 +1062,7 @@ class AstBuilder extends ScopeListener { | 
| if (identical('native', token.stringValue) && parser != null) { | 
| Token nativeKeyword = token; | 
| Token semicolon = parser.parseLiteralString(token.next); | 
| + // TODO(brianwilkerson) Should this be using ensureSemicolon? | 
| 
danrubel
2017/08/31 17:27:50
Just FYI... I'm working on removing this code beca
 
Brian Wilkerson
2017/08/31 17:29:37
Agreed.
 | 
| token = parser.expectSemicolon(semicolon); | 
| StringLiteral name = pop(); | 
| pop(); // star | 
| @@ -1167,8 +1170,7 @@ class AstBuilder extends ScopeListener { | 
| Token semicolon) { | 
| debugEvent("Import"); | 
| List<Combinator> combinators = pop(); | 
| - SimpleIdentifier prefix; | 
| - if (asKeyword != null) prefix = pop(); | 
| + SimpleIdentifier prefix = popIfNotNull(asKeyword); | 
| List<Configuration> configurations = pop(); | 
| StringLiteral uri = pop(); | 
| List<Annotation> metadata = pop(); | 
| @@ -1227,19 +1229,17 @@ class AstBuilder extends ScopeListener { | 
| void endConditionalUri(Token ifKeyword, Token equalitySign) { | 
| debugEvent("ConditionalUri"); | 
| StringLiteral libraryUri = pop(); | 
| - StringLiteral value; | 
| - if (equalitySign != null) { | 
| - value = pop(); | 
| - } | 
| + StringLiteral value = popIfNotNull(equalitySign); | 
| DottedName name = pop(); | 
| // TODO(paulberry,ahe): what if there is no `(` token due to an error in the | 
| // file being parsed? It seems like we need the parser to do adequate error | 
| // recovery and then report both the ifKeyword and leftParen tokens to the | 
| // listener. | 
| - Token leftParen = ifKeyword.next; | 
| + Token leftParen = unsafeToken(ifKeyword.next, TokenType.OPEN_PAREN); | 
| // TODO(paulberry,ahe): the parser should report the right paren token to | 
| // the listener. | 
| - Token rightParen = name.endToken.next; | 
| + Token lastToken = value?.endToken ?? equalitySign ?? name?.endToken; | 
| + Token rightParen = unsafeToken(lastToken.next, TokenType.CLOSE_PAREN); | 
| push(ast.configuration(ifKeyword, leftParen, name, equalitySign, value, | 
| rightParen, libraryUri)); | 
| } | 
| @@ -1452,7 +1452,7 @@ class AstBuilder extends ScopeListener { | 
| } | 
| // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed | 
| // in a reference to the "of" keyword. | 
| - var ofKeyword = partKeyword.next; | 
| + var ofKeyword = unsafeToken(partKeyword.next, analyzer.Keyword.OF); | 
| List<Annotation> metadata = pop(); | 
| Comment comment = pop(); | 
| directives.add(ast.partOfDirective( | 
| @@ -1719,10 +1719,12 @@ class AstBuilder extends ScopeListener { | 
| debugEvent("Enum"); | 
| List<EnumConstantDeclaration> constants = popList(count); | 
| // TODO(paulberry,ahe): the parser should pass in the openBrace token. | 
| - var openBrace = enumKeyword.next.next as analyzer.BeginToken; | 
| + var openBrace = | 
| + unsafeToken(enumKeyword.next.next, TokenType.OPEN_CURLY_BRACKET) | 
| + as analyzer.BeginToken; | 
| // TODO(paulberry): what if the '}' is missing and the parser has performed | 
| // error recovery? | 
| - Token closeBrace = openBrace.endGroup; | 
| + Token closeBrace = openBrace?.endGroup; | 
| SimpleIdentifier name = pop(); | 
| List<Annotation> metadata = pop(); | 
| Comment comment = pop(); | 
| @@ -1956,6 +1958,14 @@ class AstBuilder extends ScopeListener { | 
| } | 
| library.addCompileTimeError(message, charOffset, uri); | 
| } | 
| + | 
| + /// A marker method used to mark locations where a token is being located in | 
| + /// an unsafe way. In all such cases the parser needs to be fixed to pass in | 
| + /// the token. | 
| + Token unsafeToken(Token token, TokenType tokenType) { | 
| + // TODO(brianwilkerson) Eliminate the need for this method. | 
| + return token.type == tokenType ? token : null; | 
| + } | 
| } | 
| /// Data structure placed on the stack to represent a class body. |