Experimentally use forEach*CommentRange for both uses of getJSDocCommentRanges.

This commit is contained in:
Daniel Rosenwasser
2023-05-17 19:58:55 +00:00
parent dddd0667f0
commit 36b95b9086
3 changed files with 48 additions and 23 deletions
+9 -3
View File
@@ -92,6 +92,7 @@ import {
firstOrUndefined,
forEach,
ForEachChildNodes,
forEachJSDocCommentRangeOfNode,
ForInOrOfStatement,
ForInStatement,
ForOfStatement,
@@ -104,7 +105,6 @@ import {
getBaseFileName,
getBinaryOperatorPrecedence,
getFullWidth,
getJSDocCommentRanges,
getLanguageVariant,
getLastChild,
getLeadingCommentRanges,
@@ -166,6 +166,7 @@ import {
IterationStatement,
JSDoc,
JSDocAllType,
JSDocArray,
JSDocAugmentsTag,
JSDocAuthorTag,
JSDocCallbackTag,
@@ -239,7 +240,6 @@ import {
LiteralLikeNode,
LiteralTypeNode,
map,
mapDefined,
MappedTypeNode,
MemberExpression,
MetaProperty,
@@ -1813,7 +1813,13 @@ namespace Parser {
let hasDeprecatedTag = false;
function addJSDocComment<T extends HasJSDoc>(node: T): T {
Debug.assert(!node.jsDoc); // Should only be called once per node
const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
const jsDoc: JSDocArray = [];
forEachJSDocCommentRangeOfNode(node, sourceText, (pos, end, _kind, _hasTrailingNewline, jsDoc) => {
const comment = JSDocParser.parseJSDocComment(node, pos, end - pos);
if (comment) {
jsDoc.push(comment);
}
}, jsDoc);
if (jsDoc.length) node.jsDoc = jsDoc;
if (hasDeprecatedTag) {
hasDeprecatedTag = false;
+31 -16
View File
@@ -60,6 +60,7 @@ import {
CommentDirective,
CommentDirectivesMap,
CommentDirectiveType,
CommentKind,
CommentRange,
compareStringsCaseSensitive,
compareValues,
@@ -149,6 +150,8 @@ import {
forEachAncestorDirectory,
forEachChild,
forEachChildRecursively,
forEachLeadingCommentRange,
forEachTrailingCommentRange,
ForInOrOfStatement,
ForInStatement,
ForOfStatement,
@@ -196,7 +199,6 @@ import {
getSnippetElement,
getStringComparer,
getSymbolId,
getTrailingCommentRanges,
HasExpressionInitializer,
hasExtension,
HasFlowNode,
@@ -2395,21 +2397,34 @@ export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: Sour
}
/** @internal */
export function getJSDocCommentRanges(node: Node, text: string) {
const commentRanges = (node.kind === SyntaxKind.Parameter ||
node.kind === SyntaxKind.TypeParameter ||
node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction ||
node.kind === SyntaxKind.ParenthesizedExpression ||
node.kind === SyntaxKind.VariableDeclaration ||
node.kind === SyntaxKind.ExportSpecifier) ?
concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRanges(text, node.pos);
// True if the comment starts with '/**' but not if it is '/**/'
return filter(commentRanges, comment =>
text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash);
export function forEachJSDocCommentRangeOfNode<T, U>({ kind, pos }: Node, text: string, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined {
let result: U | undefined;
switch (kind) {
case SyntaxKind.Parameter:
case SyntaxKind.TypeParameter:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.ExportSpecifier:
result = forEachTrailingCommentRange(text, pos, runCallback, state!);
if (result) {
return result;
}
}
result = forEachLeadingCommentRange(text, pos, runCallback, state!);
if (result) {
return result;
}
function runCallback(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) {
// Only passes through comments that start with '/**', but not '/**/'
if (kind === SyntaxKind.MultiLineCommentTrivia &&
text.charCodeAt(pos + 2) === CharacterCodes.asterisk &&
text.charCodeAt(pos + 3) !== CharacterCodes.slash) {
return cb(pos, end, kind, hasTrailingNewLine, state);
}
}
}
/** @internal */
+8 -4
View File
@@ -38,13 +38,13 @@ import {
firstOrUndefined,
flatMap,
flatMapToMutable,
forEachJSDocCommentRangeOfNode,
formatting,
FunctionDeclaration,
FunctionExpression,
getAncestor,
getFirstNonSpaceCharacterPosition,
getFormatCodeSettingsForWriting,
getJSDocCommentRanges,
getLeadingCommentRanges,
getLineAndCharacterOfPosition,
getLineOfLocalPosition,
@@ -361,9 +361,13 @@ function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: C
return rangeContainsPosition(node, pos) ? pos : startPos;
}
if (leadingTriviaOption === LeadingTriviaOption.JSDoc) {
const JSDocComments = getJSDocCommentRanges(node, sourceFile.text);
if (JSDocComments?.length) {
return getLineStartPositionForPosition(JSDocComments[0].pos, sourceFile);
let commentLineStart = -1;
forEachJSDocCommentRangeOfNode(node, sourceFile.text, pos => {
commentLineStart = getLineStartPositionForPosition(pos, sourceFile);
return true;
});
if (commentLineStart >= 0) {
return commentLineStart;
}
}
const fullStart = node.getFullStart();