private _parseMemberIdentifier()

in tsdoc/src/parser/NodeParser.ts [1685:1789]


  private _parseMemberIdentifier(
    tokenReader: TokenReader,
    tokenSequenceForErrorContext: TokenSequence,
    nodeForErrorContext: DocNode
  ): DocMemberIdentifier | undefined {
    let leftQuoteExcerpt: TokenSequence | undefined = undefined;
    let rightQuoteExcerpt: TokenSequence | undefined = undefined;

    // Is this a quoted identifier?
    if (tokenReader.peekTokenKind() === TokenKind.DoubleQuote) {
      // Read the opening '"'
      tokenReader.readToken();
      leftQuoteExcerpt = tokenReader.extractAccumulatedSequence();

      // Read the text inside the quotes
      while (tokenReader.peekTokenKind() !== TokenKind.DoubleQuote) {
        if (tokenReader.peekTokenKind() === TokenKind.EndOfInput) {
          this._parserContext.log.addMessageForTokenSequence(
            TSDocMessageId.ReferenceMissingQuote,
            'Unexpected end of input inside quoted member identifier',
            leftQuoteExcerpt,
            nodeForErrorContext
          );
          return undefined;
        }

        tokenReader.readToken();
      }

      if (tokenReader.isAccumulatedSequenceEmpty()) {
        this._parserContext.log.addMessageForTokenSequence(
          TSDocMessageId.ReferenceEmptyIdentifier,
          'The quoted identifier cannot be empty',
          leftQuoteExcerpt,
          nodeForErrorContext
        );
        return undefined;
      }

      const identifierExcerpt: TokenSequence = tokenReader.extractAccumulatedSequence();

      // Read the closing '""
      tokenReader.readToken(); // read the quote
      rightQuoteExcerpt = tokenReader.extractAccumulatedSequence();

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

        leftQuoteExcerpt,
        identifierExcerpt,
        rightQuoteExcerpt
      });
    } else {
      // Otherwise assume it's a valid TypeScript identifier

      let done: boolean = false;
      while (!done) {
        switch (tokenReader.peekTokenKind()) {
          case TokenKind.AsciiWord:
          case TokenKind.DollarSign:
            tokenReader.readToken();
            break;
          default:
            done = true;
            break;
        }
      }

      if (tokenReader.isAccumulatedSequenceEmpty()) {
        this._parserContext.log.addMessageForTokenSequence(
          TSDocMessageId.ReferenceMissingIdentifier,
          'Syntax error in declaration reference: expecting a member identifier',
          tokenSequenceForErrorContext,
          nodeForErrorContext
        );
        return undefined;
      }

      const identifierExcerpt: TokenSequence = tokenReader.extractAccumulatedSequence();
      const identifier: string = identifierExcerpt.toString();

      const explanation: string | undefined = StringChecks.explainIfInvalidUnquotedMemberIdentifier(
        identifier
      );
      if (explanation) {
        this._parserContext.log.addMessageForTokenSequence(
          TSDocMessageId.ReferenceUnquotedIdentifier,
          explanation,
          identifierExcerpt,
          nodeForErrorContext
        );
        return undefined;
      }

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

        leftQuoteExcerpt,
        identifierExcerpt,
        rightQuoteExcerpt
      });
    }
  }