{"version":3,"file":"LineExtractor.js","sourceRoot":"","sources":["../../src/parser/LineExtractor.ts"],"names":[],"mappings":"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","sourcesContent":["import { TextRange } from './TextRange';\r\nimport { ParserContext } from './ParserContext';\r\nimport { TSDocMessageId } from './TSDocMessageId';\r\n\r\n// Internal parser state\r\nenum State {\r\n  // Initial state, looking for \"/*\"\r\n  BeginComment1,\r\n  // Looking for \"*\" or \"* \" after \"/*\"\r\n  BeginComment2,\r\n  // Like State.CollectingLine except immediately after the \"/**\"\r\n  CollectingFirstLine,\r\n  // Collecting characters until we reach a newline\r\n  CollectingLine,\r\n  // After a newline, looking for the \"*\" that begins a new line, or the \"*/\" to end the comment\r\n  AdvancingLine,\r\n  // Exiting the parser loop\r\n  Done\r\n}\r\n\r\n/**\r\n * The main API for parsing TSDoc comments.\r\n */\r\nexport class LineExtractor {\r\n  private static readonly _whitespaceCharacterRegExp: RegExp = /^\\s$/;\r\n\r\n  /**\r\n   * This step parses an entire code comment from slash-star-star until star-slash,\r\n   * and extracts the content lines.  The lines are stored in IDocCommentParameters.lines\r\n   * and the overall text range is assigned to IDocCommentParameters.range.\r\n   */\r\n  public static extract(parserContext: ParserContext): boolean {\r\n    const range: TextRange = parserContext.sourceRange;\r\n    const buffer: string = range.buffer;\r\n\r\n    let commentRangeStart: number = 0;\r\n    let commentRangeEnd: number = 0;\r\n\r\n    // These must be set before entering CollectingFirstLine, CollectingLine, or AdvancingLine\r\n    let collectingLineStart: number = 0;\r\n    let collectingLineEnd: number = 0;\r\n\r\n    let nextIndex: number = range.pos;\r\n    let state: State = State.BeginComment1;\r\n\r\n    const lines: TextRange[] = [];\r\n\r\n    while (state !== State.Done) {\r\n      if (nextIndex >= range.end) {\r\n        // reached the end of the input\r\n        switch (state) {\r\n          case State.BeginComment1:\r\n          case State.BeginComment2:\r\n            parserContext.log.addMessageForTextRange(\r\n              TSDocMessageId.CommentNotFound,\r\n              'Expecting a \"/**\" comment',\r\n              range\r\n            );\r\n            return false;\r\n          default:\r\n            parserContext.log.addMessageForTextRange(\r\n              TSDocMessageId.CommentMissingClosingDelimiter,\r\n              'Unexpected end of input',\r\n              range\r\n            );\r\n            return false;\r\n        }\r\n      }\r\n\r\n      const current: string = buffer[nextIndex];\r\n      const currentIndex: number = nextIndex;\r\n      ++nextIndex;\r\n      const next: string = nextIndex < range.end ? buffer[nextIndex] : '';\r\n\r\n      switch (state) {\r\n        case State.BeginComment1:\r\n          if (current === '/' && next === '*') {\r\n            commentRangeStart = currentIndex;\r\n            ++nextIndex; // skip the star\r\n            state = State.BeginComment2;\r\n          } else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {\r\n            parserContext.log.addMessageForTextRange(\r\n              TSDocMessageId.CommentOpeningDelimiterSyntax,\r\n              'Expecting a leading \"/**\"',\r\n              range.getNewRange(currentIndex, currentIndex + 1)\r\n            );\r\n            return false;\r\n          }\r\n          break;\r\n        case State.BeginComment2:\r\n          if (current === '*') {\r\n            if (next === ' ') {\r\n              ++nextIndex; // Discard the space after the star\r\n            }\r\n            collectingLineStart = nextIndex;\r\n            collectingLineEnd = nextIndex;\r\n            state = State.CollectingFirstLine;\r\n          } else {\r\n            parserContext.log.addMessageForTextRange(\r\n              TSDocMessageId.CommentOpeningDelimiterSyntax,\r\n              'Expecting a leading \"/**\"',\r\n              range.getNewRange(currentIndex, currentIndex + 1)\r\n            );\r\n            return false;\r\n          }\r\n          break;\r\n        case State.CollectingFirstLine:\r\n        case State.CollectingLine:\r\n          if (current === '\\n') {\r\n            // Ignore an empty line if it is immediately after the \"/**\"\r\n            if (state !== State.CollectingFirstLine || collectingLineEnd > collectingLineStart) {\r\n              // Record the line that we collected\r\n              lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));\r\n            }\r\n            collectingLineStart = nextIndex;\r\n            collectingLineEnd = nextIndex;\r\n            state = State.AdvancingLine;\r\n          } else if (current === '*' && next === '/') {\r\n            if (collectingLineEnd > collectingLineStart) {\r\n              lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));\r\n            }\r\n            collectingLineStart = 0;\r\n            collectingLineEnd = 0;\r\n            ++nextIndex; // skip the slash\r\n            commentRangeEnd = nextIndex;\r\n            state = State.Done;\r\n          } else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {\r\n            collectingLineEnd = nextIndex;\r\n          }\r\n          break;\r\n        case State.AdvancingLine:\r\n          if (current === '*') {\r\n            if (next === '/') {\r\n              collectingLineStart = 0;\r\n              collectingLineEnd = 0;\r\n\r\n              ++nextIndex; // skip the slash\r\n              commentRangeEnd = nextIndex;\r\n              state = State.Done;\r\n            } else {\r\n              // Discard the \"*\" at the start of a line\r\n\r\n              if (next === ' ') {\r\n                ++nextIndex; // Discard the space after the star\r\n              }\r\n\r\n              collectingLineStart = nextIndex;\r\n              collectingLineEnd = nextIndex;\r\n              state = State.CollectingLine;\r\n            }\r\n          } else if (current === '\\n') {\r\n            // Blank line\r\n            lines.push(range.getNewRange(currentIndex, currentIndex));\r\n            collectingLineStart = nextIndex;\r\n          } else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {\r\n            // If the star is missing, then start the line here\r\n            // Example: \"/**\\nL1*/\"\r\n\r\n            // (collectingLineStart was the start of this line)\r\n            collectingLineEnd = nextIndex;\r\n            state = State.CollectingLine;\r\n          }\r\n          break;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Only fill in these if we successfully scanned a comment\r\n     */\r\n    parserContext.commentRange = range.getNewRange(commentRangeStart, commentRangeEnd);\r\n    parserContext.lines = lines;\r\n    return true;\r\n  }\r\n}\r\n"]}