diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e56ff98846e..d9d2f761595 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6431,6 +6431,7 @@ namespace ts { BeginningOfLine, SawAsterisk, SavingComments, + SavingBackticks, // NOTE: Only used when parsing tag comments } const enum PropertyLikeParse { @@ -6691,18 +6692,23 @@ namespace ts { case SyntaxKind.NewLineTrivia: if (state >= JSDocState.SawAsterisk) { state = 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) { + comments.push(scanner.getTokenText()); + break; + } scanner.setTextPos(scanner.getTextPos() - 1); // falls through case SyntaxKind.EndOfFileToken: // Done break loop; case SyntaxKind.WhitespaceTrivia: - if (state === JSDocState.SavingComments) { + if (state === JSDocState.SavingComments || state === JSDocState.SavingBackticks) { pushComment(scanner.getTokenText()); } else { @@ -6724,6 +6730,15 @@ namespace ts { } pushComment(scanner.getTokenText()); break; + case SyntaxKind.BacktickToken: + if (state === JSDocState.SavingBackticks) { + state = JSDocState.SavingComments; + } + else { + state = JSDocState.SavingBackticks; + } + pushComment(scanner.getTokenText()); + break; case SyntaxKind.AsteriskToken: if (state === JSDocState.BeginningOfLine) { // leading asterisks start recording on the *next* (non-whitespace) token @@ -6734,7 +6749,9 @@ namespace ts { // record the * as a comment // falls through default: - state = JSDocState.SavingComments; // leading identifiers start recording as well + if (state !== JSDocState.SavingBackticks) { + state = JSDocState.SavingComments; // leading identifiers start recording as well + } pushComment(scanner.getTokenText()); break; } diff --git a/tests/baselines/reference/jsdocParseMatchingBackticks.symbols b/tests/baselines/reference/jsdocParseMatchingBackticks.symbols new file mode 100644 index 00000000000..83bd81113aa --- /dev/null +++ b/tests/baselines/reference/jsdocParseMatchingBackticks.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.js === +/** + * `@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) { +>f : Symbol(f, Decl(jsdocParseMatchingBackticks.js, 0, 0)) +>x : Symbol(x, Decl(jsdocParseMatchingBackticks.js, 11, 18)) +>y : Symbol(y, Decl(jsdocParseMatchingBackticks.js, 11, 20)) +>z : Symbol(z, Decl(jsdocParseMatchingBackticks.js, 11, 23)) +>alpha : Symbol(alpha, Decl(jsdocParseMatchingBackticks.js, 11, 26)) +>beta : Symbol(beta, Decl(jsdocParseMatchingBackticks.js, 11, 33)) +>gamma : Symbol(gamma, Decl(jsdocParseMatchingBackticks.js, 11, 39)) + + return x + y + z + alpha + beta + gamma +>x : Symbol(x, Decl(jsdocParseMatchingBackticks.js, 11, 18)) +>y : Symbol(y, Decl(jsdocParseMatchingBackticks.js, 11, 20)) +>z : Symbol(z, Decl(jsdocParseMatchingBackticks.js, 11, 23)) +>alpha : Symbol(alpha, Decl(jsdocParseMatchingBackticks.js, 11, 26)) +>beta : Symbol(beta, Decl(jsdocParseMatchingBackticks.js, 11, 33)) +>gamma : Symbol(gamma, Decl(jsdocParseMatchingBackticks.js, 11, 39)) +} + diff --git a/tests/baselines/reference/jsdocParseMatchingBackticks.types b/tests/baselines/reference/jsdocParseMatchingBackticks.types new file mode 100644 index 00000000000..8127e836df4 --- /dev/null +++ b/tests/baselines/reference/jsdocParseMatchingBackticks.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.js === +/** + * `@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) { +>f : (x: string, y: string, z: string, alpha: string, beta: string, gamma: string) => string +>x : string +>y : string +>z : string +>alpha : string +>beta : string +>gamma : string + + return x + y + z + alpha + beta + gamma +>x + y + z + alpha + beta + gamma : string +>x + y + z + alpha + beta : string +>x + y + z + alpha : string +>x + y + z : string +>x + y : string +>x : string +>y : string +>z : string +>alpha : string +>beta : string +>gamma : string +} + diff --git a/tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.ts b/tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.ts new file mode 100644 index 00000000000..942ee98d52f --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocParseMatchingBackticks.ts @@ -0,0 +1,20 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: jsdocParseMatchingBackticks.js + +/** + * `@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 +}