()
| 5245 | } |
| 5246 | |
| 5247 | func (p *Parser) tryParseTypeArgumentsInExpression() *ast.NodeList { |
| 5248 | // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators. |
| 5249 | // Check the cheap preconditions before saving the parser state: unless the current token is `<` |
| 5250 | // (or `<<`, which reScanLessThanToken would split), there is nothing to speculatively parse and |
| 5251 | // the mark/rewind would be a no-op. |
| 5252 | if p.contextFlags&ast.NodeFlagsJavaScriptFile != 0 || (p.token != ast.KindLessThanToken && p.token != ast.KindLessThanLessThanToken) { |
| 5253 | return nil |
| 5254 | } |
| 5255 | state := p.mark() |
| 5256 | if p.reScanLessThanToken() == ast.KindLessThanToken { |
| 5257 | p.nextToken() |
| 5258 | typeArguments := p.parseDelimitedList(PCTypeArguments, (*Parser).parseType) |
| 5259 | // If it doesn't have the closing `>` then it's definitely not an type argument list. |
| 5260 | if p.reScanGreaterThanToken() == ast.KindGreaterThanToken { |
| 5261 | p.nextToken() |
| 5262 | // We successfully parsed a type argument list. The next token determines whether we want to |
| 5263 | // treat it as such. If the type argument list is followed by `(` or a template literal, as in |
| 5264 | // `f<number>(42)`, we favor the type argument interpretation even though JavaScript would view |
| 5265 | // it as a relational expression. |
| 5266 | if p.canFollowTypeArgumentsInExpression() { |
| 5267 | return typeArguments |
| 5268 | } |
| 5269 | } |
| 5270 | } |
| 5271 | p.rewind(state) |
| 5272 | return nil |
| 5273 | } |
| 5274 | |
| 5275 | func (p *Parser) canFollowTypeArgumentsInExpression() bool { |
| 5276 | switch p.token { |
no test coverage detected