(nameToken: DirectiveNameToken)
| 704 | } |
| 705 | |
| 706 | private _consumeDirective(nameToken: DirectiveNameToken): html.Directive { |
| 707 | const attributes: html.Attribute[] = []; |
| 708 | let startSourceSpanEnd: ParseLocation = nameToken.sourceSpan.end; |
| 709 | let endSourceSpan: ParseSourceSpan | null = null; |
| 710 | this._advance(); |
| 711 | |
| 712 | if (this._peek.type === TokenType.DIRECTIVE_OPEN) { |
| 713 | // Capture the opening token in the start span. |
| 714 | startSourceSpanEnd = this._peek.sourceSpan.end; |
| 715 | this._advance(); |
| 716 | |
| 717 | // Cast here is necessary, because TS doesn't know that `_advance` changed `_peek`. |
| 718 | while ((this._peek as Token).type === TokenType.ATTR_NAME) { |
| 719 | attributes.push(this._consumeAttr(this._advance<AttributeNameToken>())); |
| 720 | } |
| 721 | |
| 722 | if ((this._peek as Token).type === TokenType.DIRECTIVE_CLOSE) { |
| 723 | endSourceSpan = this._peek.sourceSpan; |
| 724 | this._advance(); |
| 725 | } else { |
| 726 | this.errors.push( |
| 727 | TreeError.create(null, nameToken.sourceSpan, 'Unterminated directive definition'), |
| 728 | ); |
| 729 | } |
| 730 | } |
| 731 | |
| 732 | const startSourceSpan = new ParseSourceSpan( |
| 733 | nameToken.sourceSpan.start, |
| 734 | startSourceSpanEnd, |
| 735 | nameToken.sourceSpan.fullStart, |
| 736 | ); |
| 737 | |
| 738 | const sourceSpan = new ParseSourceSpan( |
| 739 | startSourceSpan.start, |
| 740 | endSourceSpan === null ? nameToken.sourceSpan.end : endSourceSpan.end, |
| 741 | startSourceSpan.fullStart, |
| 742 | ); |
| 743 | |
| 744 | return new html.Directive( |
| 745 | nameToken.parts[0], |
| 746 | attributes, |
| 747 | sourceSpan, |
| 748 | startSourceSpan, |
| 749 | endSourceSpan, |
| 750 | ); |
| 751 | } |
| 752 | |
| 753 | private _consumeBlockOpen(token: BlockOpenStartToken) { |
| 754 | const parameters: html.BlockParameter[] = []; |
no test coverage detected