From 410c3d21293f25a2674901b139344ff84b753e2e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 22 Jun 2018 17:19:20 -0700 Subject: [PATCH] Simplify getRangeOfEnclosingComment --- src/services/formatting/formatting.ts | 49 +++++++------------ src/services/formatting/smartIndenter.ts | 4 +- src/services/services.ts | 4 +- src/services/utilities.ts | 23 ++++----- .../reference/api/tsserverlibrary.d.ts | 6 +-- 5 files changed, 34 insertions(+), 52 deletions(-) diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index f37fb1bc5dddf..50af2b7557207 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1146,48 +1146,35 @@ namespace ts.formatting { export function getRangeOfEnclosingComment( sourceFile: SourceFile, position: number, - onlyMultiLine: boolean, precedingToken?: Node | null, // tslint:disable-line:no-null-keyword - tokenAtPosition = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false), - predicate?: (c: CommentRange) => boolean): CommentRange | undefined { + tokenAtPosition = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false)): CommentRange | undefined { const tokenStart = tokenAtPosition.getStart(sourceFile); if (tokenStart <= position && position < tokenAtPosition.getEnd()) { return undefined; } - if (precedingToken === undefined) { - precedingToken = findPrecedingToken(position, sourceFile); - } + precedingToken = precedingToken === null ? undefined : precedingToken === undefined ? findPrecedingToken(position, sourceFile) : precedingToken; // Between two consecutive tokens, all comments are either trailing on the former // or leading on the latter (and none are in both lists). const trailingRangesOfPreviousToken = precedingToken && getTrailingCommentRanges(sourceFile.text, precedingToken.end); const leadingCommentRangesOfNextToken = getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); - const commentRanges = trailingRangesOfPreviousToken && leadingCommentRangesOfNextToken ? - trailingRangesOfPreviousToken.concat(leadingCommentRangesOfNextToken) : - trailingRangesOfPreviousToken || leadingCommentRangesOfNextToken; - if (commentRanges) { - for (const range of commentRanges) { - // The end marker of a single-line comment does not include the newline character. - // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): - // - // // asdf ^\n - // - // But for closed multi-line comments, we don't want to be inside the comment in the following case: - // - // /* asdf */^ - // - // However, unterminated multi-line comments *do* contain their end. - // - // Internally, we represent the end of the comment at the newline and closing '/', respectively. - // - if ((range.pos < position && position < range.end || - position === range.end && (range.kind === SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth()))) { - return (range.kind === SyntaxKind.MultiLineCommentTrivia || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined; - } - } - } - return undefined; + const commentRanges = concatenate(trailingRangesOfPreviousToken, leadingCommentRangesOfNextToken); + return commentRanges && find(commentRanges, range => rangeContainsPositionExclusive(range, position) || + // The end marker of a single-line comment does not include the newline character. + // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for closed multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // However, unterminated multi-line comments *do* contain their end. + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + // + position === range.end && (range.kind === SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth())); } function getOpenTokenForList(node: Node, list: ReadonlyArray) { diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 8602347244fbf..f72871542a579 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -34,8 +34,8 @@ namespace ts.formatting { const precedingToken = findPrecedingToken(position, sourceFile); - const enclosingCommentRange = getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ true, precedingToken || null); // tslint:disable-line:no-null-keyword - if (enclosingCommentRange) { + const enclosingCommentRange = getRangeOfEnclosingComment(sourceFile, position, precedingToken || null); // tslint:disable-line:no-null-keyword + if (enclosingCommentRange && enclosingCommentRange.kind === SyntaxKind.MultiLineCommentTrivia) { return getCommentIndent(sourceFile, position, options, enclosingCommentRange); } diff --git a/src/services/services.ts b/src/services/services.ts index 29b3a4988bde8..07c934acc5272 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2034,8 +2034,8 @@ namespace ts { function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const range = formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine); - return range && createTextSpanFromRange(range); + const range = formatting.getRangeOfEnclosingComment(sourceFile, position); + return range && (!onlyMultiLine || range.kind === SyntaxKind.MultiLineCommentTrivia) ? createTextSpanFromRange(range) : undefined; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index eb710b28dc67e..bd775133256aa 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1029,12 +1029,8 @@ namespace ts { * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position) * @param predicate Additional predicate to test on the comment range. */ - export function isInComment( - sourceFile: SourceFile, - position: number, - tokenAtPosition?: Node, - predicate?: (c: CommentRange) => boolean): boolean { - return !!formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ false, /*precedingToken*/ undefined, tokenAtPosition, predicate); + export function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition?: Node): CommentRange | undefined { + return formatting.getRangeOfEnclosingComment(sourceFile, position, /*precedingToken*/ undefined, tokenAtPosition); } export function hasDocComment(sourceFile: SourceFile, position: number) { @@ -1154,17 +1150,16 @@ namespace ts { } export function isInReferenceComment(sourceFile: SourceFile, position: number): boolean { - return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, c => { - const commentText = sourceFile.text.substring(c.pos, c.end); - return tripleSlashDirectivePrefixRegex.test(commentText); - }); + return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ true); } export function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean { - return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, c => { - const commentText = sourceFile.text.substring(c.pos, c.end); - return !tripleSlashDirectivePrefixRegex.test(commentText); - }); + return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ false); + } + + function isInReferenceCommentWorker(sourceFile: SourceFile, position: number, shouldBeReference: boolean): boolean { + const range = isInComment(sourceFile, position, /*tokenAtPosition*/ undefined); + return !!range && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end)); } export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 89214bdb96c2c..d0c9f51e5d665 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -10777,7 +10777,7 @@ declare namespace ts { * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position) * @param predicate Additional predicate to test on the comment range. */ - function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition?: Node, predicate?: (c: CommentRange) => boolean): boolean; + function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition?: Node): CommentRange | undefined; function hasDocComment(sourceFile: SourceFile, position: number): boolean | undefined; function getNodeModifiers(node: Node): string; function getTypeArgumentOrTypeParameterList(node: Node): NodeArray | undefined; @@ -11388,8 +11388,8 @@ declare namespace ts.formatting { /** * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`. */ - function getRangeOfEnclosingComment(sourceFile: SourceFile, position: number, onlyMultiLine: boolean, precedingToken?: Node | null, // tslint:disable-line:no-null-keyword - tokenAtPosition?: Node, predicate?: (c: CommentRange) => boolean): CommentRange | undefined; + function getRangeOfEnclosingComment(sourceFile: SourceFile, position: number, precedingToken?: Node | null, // tslint:disable-line:no-null-keyword + tokenAtPosition?: Node): CommentRange | undefined; function getIndentationString(indentation: number, options: EditorSettings): string; } declare namespace ts.formatting {