Parses the `let` parameter of a `for` loop block.
( sourceSpan: ParseSourceSpan, expression: string, span: ParseSourceSpan, loopItemName: string, context: t.Variable[], errors: ParseError[], )
| 486 | |
| 487 | /** Parses the `let` parameter of a `for` loop block. */ |
| 488 | function parseLetParameter( |
| 489 | sourceSpan: ParseSourceSpan, |
| 490 | expression: string, |
| 491 | span: ParseSourceSpan, |
| 492 | loopItemName: string, |
| 493 | context: t.Variable[], |
| 494 | errors: ParseError[], |
| 495 | ): void { |
| 496 | const parts = expression.split(','); |
| 497 | let startSpan = span.start; |
| 498 | for (const part of parts) { |
| 499 | const expressionParts = part.split('='); |
| 500 | const name = expressionParts.length === 2 ? expressionParts[0].trim() : ''; |
| 501 | const variableName = expressionParts.length === 2 ? expressionParts[1].trim() : ''; |
| 502 | |
| 503 | if (name.length === 0 || variableName.length === 0) { |
| 504 | errors.push( |
| 505 | new ParseError( |
| 506 | sourceSpan, |
| 507 | `Invalid @for loop "let" parameter. Parameter should match the pattern "<name> = <variable name>"`, |
| 508 | ), |
| 509 | ); |
| 510 | } else if (!ALLOWED_FOR_LOOP_LET_VARIABLES.has(variableName)) { |
| 511 | errors.push( |
| 512 | new ParseError( |
| 513 | sourceSpan, |
| 514 | `Unknown "let" parameter variable "${variableName}". The allowed variables are: ${Array.from( |
| 515 | ALLOWED_FOR_LOOP_LET_VARIABLES, |
| 516 | ).join(', ')}`, |
| 517 | ), |
| 518 | ); |
| 519 | } else if (name === loopItemName) { |
| 520 | errors.push( |
| 521 | new ParseError( |
| 522 | sourceSpan, |
| 523 | `Invalid @for loop "let" parameter. Variable cannot be called "${loopItemName}"`, |
| 524 | ), |
| 525 | ); |
| 526 | } else if (context.some((v) => v.name === name)) { |
| 527 | errors.push( |
| 528 | new ParseError(sourceSpan, `Duplicate "let" parameter variable "${variableName}"`), |
| 529 | ); |
| 530 | } else { |
| 531 | const [, keyLeadingWhitespace, keyName] = |
| 532 | expressionParts[0].match(CHARACTERS_IN_SURROUNDING_WHITESPACE_PATTERN) ?? []; |
| 533 | const keySpan = |
| 534 | keyLeadingWhitespace !== undefined && expressionParts.length === 2 |
| 535 | ? new ParseSourceSpan( |
| 536 | /* strip leading spaces */ |
| 537 | startSpan.moveBy(keyLeadingWhitespace.length), |
| 538 | /* advance to end of the variable name */ |
| 539 | startSpan.moveBy(keyLeadingWhitespace.length + keyName.length), |
| 540 | ) |
| 541 | : span; |
| 542 | |
| 543 | let valueSpan: ParseSourceSpan | undefined = undefined; |
| 544 | if (expressionParts.length === 2) { |
| 545 | const [, valueLeadingWhitespace, implicit] = |