UNPKG

7.61 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.LineExtractor = void 0;
4var TSDocMessageId_1 = require("./TSDocMessageId");
5// Internal parser state
6var State;
7(function (State) {
8 // Initial state, looking for "/*"
9 State[State["BeginComment1"] = 0] = "BeginComment1";
10 // Looking for "*" or "* " after "/*"
11 State[State["BeginComment2"] = 1] = "BeginComment2";
12 // Like State.CollectingLine except immediately after the "/**"
13 State[State["CollectingFirstLine"] = 2] = "CollectingFirstLine";
14 // Collecting characters until we reach a newline
15 State[State["CollectingLine"] = 3] = "CollectingLine";
16 // After a newline, looking for the "*" that begins a new line, or the "*/" to end the comment
17 State[State["AdvancingLine"] = 4] = "AdvancingLine";
18 // Exiting the parser loop
19 State[State["Done"] = 5] = "Done";
20})(State || (State = {}));
21/**
22 * The main API for parsing TSDoc comments.
23 */
24var LineExtractor = /** @class */ (function () {
25 function LineExtractor() {
26 }
27 /**
28 * This step parses an entire code comment from slash-star-star until star-slash,
29 * and extracts the content lines. The lines are stored in IDocCommentParameters.lines
30 * and the overall text range is assigned to IDocCommentParameters.range.
31 */
32 LineExtractor.extract = function (parserContext) {
33 var range = parserContext.sourceRange;
34 var buffer = range.buffer;
35 var commentRangeStart = 0;
36 var commentRangeEnd = 0;
37 // These must be set before entering CollectingFirstLine, CollectingLine, or AdvancingLine
38 var collectingLineStart = 0;
39 var collectingLineEnd = 0;
40 var nextIndex = range.pos;
41 var state = State.BeginComment1;
42 var lines = [];
43 while (state !== State.Done) {
44 if (nextIndex >= range.end) {
45 // reached the end of the input
46 switch (state) {
47 case State.BeginComment1:
48 case State.BeginComment2:
49 parserContext.log.addMessageForTextRange(TSDocMessageId_1.TSDocMessageId.CommentNotFound, 'Expecting a "/**" comment', range);
50 return false;
51 default:
52 parserContext.log.addMessageForTextRange(TSDocMessageId_1.TSDocMessageId.CommentMissingClosingDelimiter, 'Unexpected end of input', range);
53 return false;
54 }
55 }
56 var current = buffer[nextIndex];
57 var currentIndex = nextIndex;
58 ++nextIndex;
59 var next = nextIndex < range.end ? buffer[nextIndex] : '';
60 switch (state) {
61 case State.BeginComment1:
62 if (current === '/' && next === '*') {
63 commentRangeStart = currentIndex;
64 ++nextIndex; // skip the star
65 state = State.BeginComment2;
66 }
67 else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
68 parserContext.log.addMessageForTextRange(TSDocMessageId_1.TSDocMessageId.CommentOpeningDelimiterSyntax, 'Expecting a leading "/**"', range.getNewRange(currentIndex, currentIndex + 1));
69 return false;
70 }
71 break;
72 case State.BeginComment2:
73 if (current === '*') {
74 if (next === ' ') {
75 ++nextIndex; // Discard the space after the star
76 }
77 collectingLineStart = nextIndex;
78 collectingLineEnd = nextIndex;
79 state = State.CollectingFirstLine;
80 }
81 else {
82 parserContext.log.addMessageForTextRange(TSDocMessageId_1.TSDocMessageId.CommentOpeningDelimiterSyntax, 'Expecting a leading "/**"', range.getNewRange(currentIndex, currentIndex + 1));
83 return false;
84 }
85 break;
86 case State.CollectingFirstLine:
87 case State.CollectingLine:
88 if (current === '\n') {
89 // Ignore an empty line if it is immediately after the "/**"
90 if (state !== State.CollectingFirstLine || collectingLineEnd > collectingLineStart) {
91 // Record the line that we collected
92 lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));
93 }
94 collectingLineStart = nextIndex;
95 collectingLineEnd = nextIndex;
96 state = State.AdvancingLine;
97 }
98 else if (current === '*' && next === '/') {
99 if (collectingLineEnd > collectingLineStart) {
100 lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));
101 }
102 collectingLineStart = 0;
103 collectingLineEnd = 0;
104 ++nextIndex; // skip the slash
105 commentRangeEnd = nextIndex;
106 state = State.Done;
107 }
108 else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
109 collectingLineEnd = nextIndex;
110 }
111 break;
112 case State.AdvancingLine:
113 if (current === '*') {
114 if (next === '/') {
115 collectingLineStart = 0;
116 collectingLineEnd = 0;
117 ++nextIndex; // skip the slash
118 commentRangeEnd = nextIndex;
119 state = State.Done;
120 }
121 else {
122 // Discard the "*" at the start of a line
123 if (next === ' ') {
124 ++nextIndex; // Discard the space after the star
125 }
126 collectingLineStart = nextIndex;
127 collectingLineEnd = nextIndex;
128 state = State.CollectingLine;
129 }
130 }
131 else if (current === '\n') {
132 // Blank line
133 lines.push(range.getNewRange(currentIndex, currentIndex));
134 collectingLineStart = nextIndex;
135 }
136 else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
137 // If the star is missing, then start the line here
138 // Example: "/**\nL1*/"
139 // (collectingLineStart was the start of this line)
140 collectingLineEnd = nextIndex;
141 state = State.CollectingLine;
142 }
143 break;
144 }
145 }
146 /**
147 * Only fill in these if we successfully scanned a comment
148 */
149 parserContext.commentRange = range.getNewRange(commentRangeStart, commentRangeEnd);
150 parserContext.lines = lines;
151 return true;
152 };
153 LineExtractor._whitespaceCharacterRegExp = /^\s$/;
154 return LineExtractor;
155}());
156exports.LineExtractor = LineExtractor;
157//# sourceMappingURL=LineExtractor.js.map
\No newline at end of file