154 lines
7.2 KiB
JavaScript
154 lines
7.2 KiB
JavaScript
import { TSDocMessageId } from './TSDocMessageId';
|
|
// Internal parser state
|
|
var State;
|
|
(function (State) {
|
|
// Initial state, looking for "/*"
|
|
State[State["BeginComment1"] = 0] = "BeginComment1";
|
|
// Looking for "*" or "* " after "/*"
|
|
State[State["BeginComment2"] = 1] = "BeginComment2";
|
|
// Like State.CollectingLine except immediately after the "/**"
|
|
State[State["CollectingFirstLine"] = 2] = "CollectingFirstLine";
|
|
// Collecting characters until we reach a newline
|
|
State[State["CollectingLine"] = 3] = "CollectingLine";
|
|
// After a newline, looking for the "*" that begins a new line, or the "*/" to end the comment
|
|
State[State["AdvancingLine"] = 4] = "AdvancingLine";
|
|
// Exiting the parser loop
|
|
State[State["Done"] = 5] = "Done";
|
|
})(State || (State = {}));
|
|
/**
|
|
* The main API for parsing TSDoc comments.
|
|
*/
|
|
var LineExtractor = /** @class */ (function () {
|
|
function LineExtractor() {
|
|
}
|
|
/**
|
|
* This step parses an entire code comment from slash-star-star until star-slash,
|
|
* and extracts the content lines. The lines are stored in IDocCommentParameters.lines
|
|
* and the overall text range is assigned to IDocCommentParameters.range.
|
|
*/
|
|
LineExtractor.extract = function (parserContext) {
|
|
var range = parserContext.sourceRange;
|
|
var buffer = range.buffer;
|
|
var commentRangeStart = 0;
|
|
var commentRangeEnd = 0;
|
|
// These must be set before entering CollectingFirstLine, CollectingLine, or AdvancingLine
|
|
var collectingLineStart = 0;
|
|
var collectingLineEnd = 0;
|
|
var nextIndex = range.pos;
|
|
var state = State.BeginComment1;
|
|
var lines = [];
|
|
while (state !== State.Done) {
|
|
if (nextIndex >= range.end) {
|
|
// reached the end of the input
|
|
switch (state) {
|
|
case State.BeginComment1:
|
|
case State.BeginComment2:
|
|
parserContext.log.addMessageForTextRange(TSDocMessageId.CommentNotFound, 'Expecting a "/**" comment', range);
|
|
return false;
|
|
default:
|
|
parserContext.log.addMessageForTextRange(TSDocMessageId.CommentMissingClosingDelimiter, 'Unexpected end of input', range);
|
|
return false;
|
|
}
|
|
}
|
|
var current = buffer[nextIndex];
|
|
var currentIndex = nextIndex;
|
|
++nextIndex;
|
|
var next = nextIndex < range.end ? buffer[nextIndex] : '';
|
|
switch (state) {
|
|
case State.BeginComment1:
|
|
if (current === '/' && next === '*') {
|
|
commentRangeStart = currentIndex;
|
|
++nextIndex; // skip the star
|
|
state = State.BeginComment2;
|
|
}
|
|
else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
|
|
parserContext.log.addMessageForTextRange(TSDocMessageId.CommentOpeningDelimiterSyntax, 'Expecting a leading "/**"', range.getNewRange(currentIndex, currentIndex + 1));
|
|
return false;
|
|
}
|
|
break;
|
|
case State.BeginComment2:
|
|
if (current === '*') {
|
|
if (next === ' ') {
|
|
++nextIndex; // Discard the space after the star
|
|
}
|
|
collectingLineStart = nextIndex;
|
|
collectingLineEnd = nextIndex;
|
|
state = State.CollectingFirstLine;
|
|
}
|
|
else {
|
|
parserContext.log.addMessageForTextRange(TSDocMessageId.CommentOpeningDelimiterSyntax, 'Expecting a leading "/**"', range.getNewRange(currentIndex, currentIndex + 1));
|
|
return false;
|
|
}
|
|
break;
|
|
case State.CollectingFirstLine:
|
|
case State.CollectingLine:
|
|
if (current === '\n') {
|
|
// Ignore an empty line if it is immediately after the "/**"
|
|
if (state !== State.CollectingFirstLine || collectingLineEnd > collectingLineStart) {
|
|
// Record the line that we collected
|
|
lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));
|
|
}
|
|
collectingLineStart = nextIndex;
|
|
collectingLineEnd = nextIndex;
|
|
state = State.AdvancingLine;
|
|
}
|
|
else if (current === '*' && next === '/') {
|
|
if (collectingLineEnd > collectingLineStart) {
|
|
lines.push(range.getNewRange(collectingLineStart, collectingLineEnd));
|
|
}
|
|
collectingLineStart = 0;
|
|
collectingLineEnd = 0;
|
|
++nextIndex; // skip the slash
|
|
commentRangeEnd = nextIndex;
|
|
state = State.Done;
|
|
}
|
|
else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
|
|
collectingLineEnd = nextIndex;
|
|
}
|
|
break;
|
|
case State.AdvancingLine:
|
|
if (current === '*') {
|
|
if (next === '/') {
|
|
collectingLineStart = 0;
|
|
collectingLineEnd = 0;
|
|
++nextIndex; // skip the slash
|
|
commentRangeEnd = nextIndex;
|
|
state = State.Done;
|
|
}
|
|
else {
|
|
// Discard the "*" at the start of a line
|
|
if (next === ' ') {
|
|
++nextIndex; // Discard the space after the star
|
|
}
|
|
collectingLineStart = nextIndex;
|
|
collectingLineEnd = nextIndex;
|
|
state = State.CollectingLine;
|
|
}
|
|
}
|
|
else if (current === '\n') {
|
|
// Blank line
|
|
lines.push(range.getNewRange(currentIndex, currentIndex));
|
|
collectingLineStart = nextIndex;
|
|
}
|
|
else if (!LineExtractor._whitespaceCharacterRegExp.test(current)) {
|
|
// If the star is missing, then start the line here
|
|
// Example: "/**\nL1*/"
|
|
// (collectingLineStart was the start of this line)
|
|
collectingLineEnd = nextIndex;
|
|
state = State.CollectingLine;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/**
|
|
* Only fill in these if we successfully scanned a comment
|
|
*/
|
|
parserContext.commentRange = range.getNewRange(commentRangeStart, commentRangeEnd);
|
|
parserContext.lines = lines;
|
|
return true;
|
|
};
|
|
LineExtractor._whitespaceCharacterRegExp = /^\s$/;
|
|
return LineExtractor;
|
|
}());
|
|
export { LineExtractor };
|
|
//# sourceMappingURL=LineExtractor.js.map
|