private _parseBlockTag()

in tsdoc/src/parser/NodeParser.ts [707:788]


  private _parseBlockTag(tokenReader: TokenReader): DocNode {
    tokenReader.assertAccumulatedSequenceIsEmpty();
    const marker: number = tokenReader.createMarker();

    if (tokenReader.peekTokenKind() !== TokenKind.AtSign) {
      return this._backtrackAndCreateError(
        tokenReader,
        marker,
        TSDocMessageId.MissingTag,
        'Expecting a TSDoc tag starting with "@"'
      );
    }

    // "@one" is a valid TSDoc tag at the start of a line, but "@one@two" is
    // a syntax error.  For two tags it should be "@one @two", or for literal text it
    // should be "\@one\@two".
    switch (tokenReader.peekPreviousTokenKind()) {
      case TokenKind.EndOfInput:
      case TokenKind.Spacing:
      case TokenKind.Newline:
        break;
      default:
        return this._backtrackAndCreateError(
          tokenReader,
          marker,
          TSDocMessageId.AtSignInWord,
          'The "@" character looks like part of a TSDoc tag; use a backslash to escape it'
        );
    }

    // Include the "@" as part of the tagName
    let tagName: string = tokenReader.readToken().toString();

    if (tokenReader.peekTokenKind() !== TokenKind.AsciiWord) {
      return this._backtrackAndCreateError(
        tokenReader,
        marker,
        TSDocMessageId.AtSignWithoutTagName,
        'Expecting a TSDoc tag name after "@"; if it is not a tag, use a backslash to escape this character'
      );
    }

    const tagNameMarker: number = tokenReader.createMarker();

    while (tokenReader.peekTokenKind() === TokenKind.AsciiWord) {
      tagName += tokenReader.readToken().toString();
    }

    switch (tokenReader.peekTokenKind()) {
      case TokenKind.Spacing:
      case TokenKind.Newline:
      case TokenKind.EndOfInput:
        break;
      default:
        const badCharacter: string = tokenReader.peekToken().range.toString()[0];
        return this._backtrackAndCreateError(
          tokenReader,
          marker,
          TSDocMessageId.CharactersAfterBlockTag,
          `The token "${tagName}" looks like a TSDoc tag but contains an invalid character` +
            ` ${JSON.stringify(badCharacter)}; if it is not a tag, use a backslash to escape the "@"`
        );
    }

    if (StringChecks.explainIfInvalidTSDocTagName(tagName)) {
      const failure: IFailure = this._createFailureForTokensSince(
        tokenReader,
        TSDocMessageId.MalformedTagName,
        'A TSDoc tag name must start with a letter and contain only letters and numbers',
        tagNameMarker
      );
      return this._backtrackAndCreateErrorForFailure(tokenReader, marker, '', failure);
    }

    return new DocBlockTag({
      parsed: true,
      configuration: this._configuration,

      tagName,
      tagNameExcerpt: tokenReader.extractAccumulatedSequence()
    });
  }