From d3e5dac9322eadf5e85144cfdb7cf94ddae0fa35 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 27 Apr 2022 10:49:56 -0700 Subject: [PATCH] Stop tag after @callback from crashing By copying the kludge in @typedef. @callback's order is simpler, so the kludge is simpler. However, it's wrong here, and in @typedef. Parsing tag comments is normally supposed to happen at the end of a tag, but in @callback and @typedef happens *before* parsing the nested @param/@property tags. I still need to figure out what a real fix is -- but for the beta, copying the existing crash-avoidance kludge from @typedef is best anyway. I added a test case for typedefs for future use as well. --- src/compiler/parser.ts | 3 ++- tests/cases/fourslash/jsTagAfterCallback1.ts | 19 +++++++++++++++++++ tests/cases/fourslash/jsTagAfterCallback2.ts | 19 +++++++++++++++++++ tests/cases/fourslash/jsTagAfterTypedef1.ts | 19 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/jsTagAfterCallback1.ts create mode 100644 tests/cases/fourslash/jsTagAfterCallback2.ts create mode 100644 tests/cases/fourslash/jsTagAfterTypedef1.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e57a3fa98f390..884a5b36e38c1 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -8579,7 +8579,8 @@ namespace ts { if (!comment) { comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); } - return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start); + const end = comment !== undefined ? getNodePos() : typeExpression.end; + return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); } function escapedTextsEqual(a: EntityName, b: EntityName): boolean { diff --git a/tests/cases/fourslash/jsTagAfterCallback1.ts b/tests/cases/fourslash/jsTagAfterCallback1.ts new file mode 100644 index 0000000000000..cc270afcf399e --- /dev/null +++ b/tests/cases/fourslash/jsTagAfterCallback1.ts @@ -0,0 +1,19 @@ +/// +// @Filename: foo.js +// @allowJs: true +// @checkJs: true +//// /** @callback Listener @yeturn {ListenerBlock} */ +//// /** +//// * The function used +//// * /*1*/ settings +//// */ +//// class /*2*/ListenerBlock { +//// } + +// Force a syntax tree to be created. +verify.noMatchingBracePositionInCurrentFile(0); + +goTo.marker('1'); +edit.insert('fenster'); + +verify.quickInfoAt('2', 'class ListenerBlock', 'The function used\nfenster settings') diff --git a/tests/cases/fourslash/jsTagAfterCallback2.ts b/tests/cases/fourslash/jsTagAfterCallback2.ts new file mode 100644 index 0000000000000..3cfa493f32abf --- /dev/null +++ b/tests/cases/fourslash/jsTagAfterCallback2.ts @@ -0,0 +1,19 @@ +/// +// @Filename: foo.js +// @allowJs: true +// @checkJs: true +//// /** @callback Listener @param x @yeturn {ListenerBlock} */ +//// /** +//// * The function used +//// * /*1*/ settings +//// */ +//// class /*2*/ListenerBlock { +//// } + +// Force a syntax tree to be created. +verify.noMatchingBracePositionInCurrentFile(0); + +goTo.marker('1'); +edit.insert('fenster'); + +verify.quickInfoAt('2', 'class ListenerBlock', 'The function used\nfenster settings') diff --git a/tests/cases/fourslash/jsTagAfterTypedef1.ts b/tests/cases/fourslash/jsTagAfterTypedef1.ts new file mode 100644 index 0000000000000..d0cf99e6f1804 --- /dev/null +++ b/tests/cases/fourslash/jsTagAfterTypedef1.ts @@ -0,0 +1,19 @@ +/// +// @Filename: foo.js +// @allowJs: true +// @checkJs: true +//// /** @typedef Lister @property p @yeturn {ListenerBlock} */ +//// /** +//// * The function used +//// * /*1*/ settings +//// */ +//// class /*2*/ListenerBlock { +//// } + +// Force a syntax tree to be created. +verify.noMatchingBracePositionInCurrentFile(0); + +goTo.marker('1'); +edit.insert('fenster'); + +verify.quickInfoAt('2', 'class ListenerBlock', 'The function used\nfenster settings')