| 830 | } |
| 831 | |
| 832 | private _consumeLet(startToken: LetStartToken) { |
| 833 | const name = startToken.parts[0]; |
| 834 | let valueToken: LetValueToken; |
| 835 | let endToken: LetEndToken; |
| 836 | |
| 837 | if (this._peek.type !== TokenType.LET_VALUE) { |
| 838 | this.errors.push( |
| 839 | TreeError.create( |
| 840 | startToken.parts[0], |
| 841 | startToken.sourceSpan, |
| 842 | `Invalid @let declaration "${name}". Declaration must have a value.`, |
| 843 | ), |
| 844 | ); |
| 845 | return; |
| 846 | } else { |
| 847 | valueToken = this._advance(); |
| 848 | } |
| 849 | |
| 850 | // Type cast is necessary here since TS narrowed the type of `peek` above. |
| 851 | if ((this._peek as Token).type !== TokenType.LET_END) { |
| 852 | this.errors.push( |
| 853 | TreeError.create( |
| 854 | startToken.parts[0], |
| 855 | startToken.sourceSpan, |
| 856 | `Unterminated @let declaration "${name}". Declaration must be terminated with a semicolon.`, |
| 857 | ), |
| 858 | ); |
| 859 | return; |
| 860 | } else { |
| 861 | endToken = this._advance(); |
| 862 | } |
| 863 | |
| 864 | const end = endToken.sourceSpan.end; |
| 865 | const span = new ParseSourceSpan( |
| 866 | startToken.sourceSpan.start, |
| 867 | end, |
| 868 | startToken.sourceSpan.fullStart, |
| 869 | ); |
| 870 | |
| 871 | // The start token usually captures the `@let`. Construct a name span by |
| 872 | // offsetting the start by the length of any text before the name. |
| 873 | const startOffset = startToken.sourceSpan.toString().lastIndexOf(name); |
| 874 | const nameStart = startToken.sourceSpan.start.moveBy(startOffset); |
| 875 | const nameSpan = new ParseSourceSpan(nameStart, startToken.sourceSpan.end); |
| 876 | const node = new html.LetDeclaration( |
| 877 | name, |
| 878 | valueToken.parts[0], |
| 879 | span, |
| 880 | nameSpan, |
| 881 | valueToken.sourceSpan, |
| 882 | ); |
| 883 | |
| 884 | this._addToParent(node); |
| 885 | } |
| 886 | |
| 887 | private _consumeIncompleteLet(token: IncompleteLetToken) { |
| 888 | // Incomplete `@let` declaration may end up with an empty name. |