mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
JSDoc comment parsing supports multiline backticks
Previously, backticks in JSDoc ended at the end of a line. This PR changes that so that backticks continue parsing until another backtick. Note that triple backticks and single backticks are treated the same way. The change is already very clunky, and I haven't thought about how much clunkier it would be to track backtick history in the parser.
This commit is contained in:
+18
-5
@@ -8123,6 +8123,8 @@ namespace ts {
|
||||
SawAsterisk,
|
||||
SavingComments,
|
||||
SavingBackticks, // NOTE: Only used when parsing tag comments
|
||||
SavingBackticksBeginningOfLine,
|
||||
SavingBackticksSawAsterisk,
|
||||
}
|
||||
|
||||
const enum PropertyLikeParse {
|
||||
@@ -8433,13 +8435,13 @@ namespace ts {
|
||||
loop: while (true) {
|
||||
switch (tok) {
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
state = JSDocState.BeginningOfLine;
|
||||
state = (state as JSDocState) === JSDocState.SavingBackticks || (state as JSDocState) === JSDocState.SavingBackticksBeginningOfLine || (state as JSDocState) === JSDocState.SavingBackticksSawAsterisk ? JSDocState.SavingBackticksBeginningOfLine : JSDocState.BeginningOfLine;
|
||||
// don't use pushComment here because we want to keep the margin unchanged
|
||||
comments.push(scanner.getTokenText());
|
||||
indent = 0;
|
||||
break;
|
||||
case SyntaxKind.AtToken:
|
||||
if (state === JSDocState.SavingBackticks
|
||||
if (state === JSDocState.SavingBackticks || state === JSDocState.SavingBackticksBeginningOfLine || state === JSDocState.SavingBackticksSawAsterisk
|
||||
|| state === JSDocState.SavingComments && (!previousWhitespace || lookAhead(isNextJSDocTokenWhitespace))) {
|
||||
// @ doesn't start a new tag inside ``, and inside a comment, only after whitespace or not before whitespace
|
||||
comments.push(scanner.getTokenText());
|
||||
@@ -8464,7 +8466,7 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
state = JSDocState.SavingComments;
|
||||
state = (state as JSDocState) === JSDocState.SavingBackticks || (state as JSDocState) === JSDocState.SavingBackticksBeginningOfLine || (state as JSDocState) === JSDocState.SavingBackticksSawAsterisk ? JSDocState.SavingBackticks : JSDocState.SavingComments;
|
||||
const commentEnd = scanner.getStartPos();
|
||||
const linkStart = scanner.getTextPos() - 1;
|
||||
const link = parseJSDocLink(linkStart);
|
||||
@@ -8479,7 +8481,7 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.BacktickToken:
|
||||
if (state === JSDocState.SavingBackticks) {
|
||||
if (state === JSDocState.SavingBackticks || state === JSDocState.SavingBackticksBeginningOfLine || state === JSDocState.SavingBackticksSawAsterisk) {
|
||||
state = JSDocState.SavingComments;
|
||||
}
|
||||
else {
|
||||
@@ -8494,11 +8496,22 @@ namespace ts {
|
||||
indent += 1;
|
||||
break;
|
||||
}
|
||||
if (state === JSDocState.SavingBackticksBeginningOfLine) {
|
||||
// leading asterisks start recording on the *next* (non-whitespace) token
|
||||
state = JSDocState.SavingBackticksSawAsterisk;
|
||||
indent += 1;
|
||||
break;
|
||||
}
|
||||
// record the * as a comment
|
||||
// falls through
|
||||
default:
|
||||
if (state !== JSDocState.SavingBackticks) {
|
||||
state = JSDocState.SavingComments; // leading identifiers start recording as well
|
||||
if (state === JSDocState.SavingBackticksBeginningOfLine || state === JSDocState.SavingBackticksSawAsterisk) {
|
||||
state = JSDocState.SavingBackticks
|
||||
}
|
||||
else {
|
||||
state = JSDocState.SavingComments; // leading identifiers start recording as well
|
||||
}
|
||||
}
|
||||
pushComment(scanner.getTokenText());
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.js(22,22): error TS7006: Parameter 'gamma' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.js (1 errors) ====
|
||||
/**
|
||||
* `@param` initial at-param is OK in title comment
|
||||
* @param {string} x hi there `@param`
|
||||
* @param {string} y hi there @ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
`@param` @param {string} z hello???
|
||||
* `@param` @param {string} alpha hello???
|
||||
* `@ * param` @param {string} beta hello???
|
||||
* @param {string} gamma
|
||||
*/
|
||||
export function f(x, y, z, alpha, beta, gamma) {
|
||||
return x + y + z + alpha + beta + gamma
|
||||
}
|
||||
/**
|
||||
* Unmatched backticks keep going past newlines
|
||||
* @param {string} y hi there `@ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
* @param {string} gamma
|
||||
*/
|
||||
export function g(y, gamma) {
|
||||
~~~~~
|
||||
!!! error TS7006: Parameter 'gamma' implicitly has an 'any' type.
|
||||
return y + gamma
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* `@param` initial at-param is OK in title comment
|
||||
* @param {string} x hi there `@param`
|
||||
* @param {string} y hi there `@ * param
|
||||
* @param {string} y hi there @ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
`@param` @param {string} z hello???
|
||||
@@ -27,4 +27,20 @@ export function f(x, y, z, alpha, beta, gamma) {
|
||||
>beta : Symbol(beta, Decl(jsdocParseMatchingBackticks.js, 11, 33))
|
||||
>gamma : Symbol(gamma, Decl(jsdocParseMatchingBackticks.js, 11, 39))
|
||||
}
|
||||
/**
|
||||
* Unmatched backticks keep going past newlines
|
||||
* @param {string} y hi there `@ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
* @param {string} gamma
|
||||
*/
|
||||
export function g(y, gamma) {
|
||||
>g : Symbol(g, Decl(jsdocParseMatchingBackticks.js, 13, 1))
|
||||
>y : Symbol(y, Decl(jsdocParseMatchingBackticks.js, 21, 18))
|
||||
>gamma : Symbol(gamma, Decl(jsdocParseMatchingBackticks.js, 21, 20))
|
||||
|
||||
return y + gamma
|
||||
>y : Symbol(y, Decl(jsdocParseMatchingBackticks.js, 21, 18))
|
||||
>gamma : Symbol(gamma, Decl(jsdocParseMatchingBackticks.js, 21, 20))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* `@param` initial at-param is OK in title comment
|
||||
* @param {string} x hi there `@param`
|
||||
* @param {string} y hi there `@ * param
|
||||
* @param {string} y hi there @ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
`@param` @param {string} z hello???
|
||||
@@ -32,4 +32,21 @@ export function f(x, y, z, alpha, beta, gamma) {
|
||||
>beta : string
|
||||
>gamma : string
|
||||
}
|
||||
/**
|
||||
* Unmatched backticks keep going past newlines
|
||||
* @param {string} y hi there `@ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
* @param {string} gamma
|
||||
*/
|
||||
export function g(y, gamma) {
|
||||
>g : (y: string, gamma: any) => string
|
||||
>y : string
|
||||
>gamma : any
|
||||
|
||||
return y + gamma
|
||||
>y + gamma : string
|
||||
>y : string
|
||||
>gamma : any
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/**
|
||||
* `@param` initial at-param is OK in title comment
|
||||
* @param {string} x hi there `@param`
|
||||
* @param {string} y hi there `@ * param
|
||||
* @param {string} y hi there @ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
`@param` @param {string} z hello???
|
||||
@@ -18,3 +18,13 @@
|
||||
export function f(x, y, z, alpha, beta, gamma) {
|
||||
return x + y + z + alpha + beta + gamma
|
||||
}
|
||||
/**
|
||||
* Unmatched backticks keep going past newlines
|
||||
* @param {string} y hi there `@ * param
|
||||
* this is the margin
|
||||
* so we'll drop everything before it
|
||||
* @param {string} gamma
|
||||
*/
|
||||
export function g(y, gamma) {
|
||||
return y + gamma
|
||||
}
|
||||
|
||||
@@ -11,15 +11,18 @@
|
||||
//// * @param {string} x hi there `@param`
|
||||
//// * @param {string} y hi there `@ * param
|
||||
//// * this is the margin
|
||||
//// * @param {string} z OOPS, unclosed backtick!
|
||||
//// */
|
||||
////export function f(x, y) {
|
||||
//// return x/*x*/ + y/*y*/
|
||||
////export function f(x, y, z) {
|
||||
//// return x/*x*/ + y/*y*/ + z/*z*/
|
||||
////}
|
||||
////f/*f*/
|
||||
|
||||
goTo.marker("f");
|
||||
verify.quickInfoIs("function f(x: string, y: string): string", "`@param` initial at-param is OK in title comment");
|
||||
verify.quickInfoIs("function f(x: string, y: string, z: any): string", "`@param` initial at-param is OK in title comment");
|
||||
goTo.marker("x");
|
||||
verify.quickInfoIs("(parameter) x: string", "hi there `@param`");
|
||||
goTo.marker("y");
|
||||
verify.quickInfoIs("(parameter) y: string", "hi there `@ * param\nthis is the margin");
|
||||
verify.quickInfoIs("(parameter) y: string", "hi there `@ * param\nthis is the margin\n@param {string} z OOPS, unclosed backtick!");
|
||||
goTo.marker("z");
|
||||
verify.quickInfoIs("(parameter) z: any", undefined);
|
||||
|
||||
Reference in New Issue
Block a user