(start: CharacterCursor)
| 295 | } |
| 296 | |
| 297 | private _consumeBlockStart(start: CharacterCursor) { |
| 298 | this._requireCharCode(chars.$AT); |
| 299 | this._beginToken(TokenType.BLOCK_OPEN_START, start); |
| 300 | const startToken = this._endToken([this._getBlockName()]); |
| 301 | |
| 302 | if (this._cursor.peek() === chars.$LPAREN) { |
| 303 | // Advance past the opening paren. |
| 304 | this._cursor.advance(); |
| 305 | // Capture the parameters. |
| 306 | this._consumeBlockParameters(); |
| 307 | // Allow spaces before the closing paren. |
| 308 | this._attemptCharCodeUntilFn(isNotWhitespace); |
| 309 | |
| 310 | if (this._attemptCharCode(chars.$RPAREN)) { |
| 311 | // Allow spaces after the paren. |
| 312 | this._attemptCharCodeUntilFn(isNotWhitespace); |
| 313 | } else { |
| 314 | startToken.type = TokenType.INCOMPLETE_BLOCK_OPEN; |
| 315 | return; |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | if (startToken.parts[0] === 'default never' && this._attemptCharCode(chars.$SEMICOLON)) { |
| 320 | this._beginToken(TokenType.BLOCK_OPEN_END); |
| 321 | this._endToken([]); |
| 322 | this._beginToken(TokenType.BLOCK_CLOSE); |
| 323 | this._endToken([]); |
| 324 | return; |
| 325 | } |
| 326 | |
| 327 | if (this._attemptCharCode(chars.$LBRACE)) { |
| 328 | this._beginToken(TokenType.BLOCK_OPEN_END); |
| 329 | this._endToken([]); |
| 330 | } else if ( |
| 331 | this._isBlockStart() && |
| 332 | (startToken.parts[0] === 'case' || startToken.parts[0] === 'default') |
| 333 | ) { |
| 334 | // We only allow @case statements to be consecutive without a block in between. |
| 335 | this._beginToken(TokenType.BLOCK_OPEN_END); |
| 336 | this._endToken([]); |
| 337 | this._beginToken(TokenType.BLOCK_CLOSE); |
| 338 | this._endToken([]); |
| 339 | } else { |
| 340 | startToken.type = TokenType.INCOMPLETE_BLOCK_OPEN; |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | private _consumeBlockEnd(start: CharacterCursor) { |
| 345 | this._beginToken(TokenType.BLOCK_CLOSE, start); |
no test coverage detected