From ece9f3410e24b1fec622a84d7b438718afa0dbc0 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Mon, 30 Mar 2020 23:20:00 +0900 Subject: [PATCH 01/10] fix broken regex on src/services/completions.ts#840 --- src/services/completions.ts | 53 ++++++++++---------- tests/cases/fourslash/completionsJsdocTag.ts | 49 ++++++++++++++++++ 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index a1e98a03d8708..f8db6f274d40d 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -852,32 +852,33 @@ namespace ts.Completions { let isInSnippetScope = false; if (insideComment) { if (hasDocComment(sourceFile, position)) { - if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - return { kind: CompletionDataKind.JsDocTagName }; - } - else { - // When completion is requested without "@", we will have check to make sure that - // there are no comments prefix the request position. We will only allow "*" and space. - // e.g - // /** |c| /* - // - // /** - // |c| - // */ - // - // /** - // * |c| - // */ - // - // /** - // * |c| - // */ - const lineStart = getLineStartPositionForPosition(position, sourceFile); - if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { - return { kind: CompletionDataKind.JsDocTag }; - } + // When completion is requested without "@", we will have check to make sure that + // there are no comments prefix the request position. We will only allow "*" and space. + // e.g + // /** |c| /* + // + // /** + // |c| + // */ + // + // /** + // * |c| + // */ + // + // /** + // * |c| + // */ + const lineStart = getLineStartPositionForPosition(position, sourceFile); + // jsdoc tag will be listed if there is more than one whitespace after "*" + const match = /^\s*(?:[*\s]+(?=\s)|\/\*\*)?\s+(@)?$/.exec( + sourceFile.text.substring(lineStart, position) + ); + if (match) { + return { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + kind: match[1] ? CompletionDataKind.JsDocTagName: CompletionDataKind.JsDocTag + }; } } diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 71a7a97bc6e61..8cfdd467ea2ec 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -5,4 +5,53 @@ //// * /**/ //// */ +/////** +//// +/*1*/ +//// */ +////function a0(s: string) {} +//// + verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); + + +// +// test for src/services/completions.ts#getCompletionData.insideComment.hasDocComment (#37546) +// +// line 2: [ +|c|] +verify.completions({ + marker: "1", + exact: [] +}); +// line 2: [ +|c|] -> [ +@|c|] +// before the fix, jsdoc tag names was listed but no longer appears +edit.insert("@"); +verify.completions({ + marker: "1", + exact: [] +}); +// line 2: [ +@|c|] -> [ *|c|] +// before the fix, jsdoc tags was listed but no longer appears +edit.replaceLine(1, " *"); +verify.completions({ + exact: [] +}); +// line 2: [ *|c|] -> [ *@|c|] +// this behavior does not by getCompletionData.insideComment.hasDocComment section +edit.insert("@"); +verify.completions({ + triggerCharacter: "@", + includes: ["abstract", "access"] +}); +// line 2: [ *@|c|] -> [ * |c|] +// jsdoc tags are listed when there is more than one whitespace after "*" +edit.replaceLine(1, " * "); +verify.completions({ + includes: ["@abstract", "@access"] +}); +// line 2: [ * |c|] -> [ * @|c|] +// jsdoc tag names will be listed +edit.insert("@"); +verify.completions({ + triggerCharacter: "@", + includes: ["abstract", "access"] +}); From ff454d5d16056196512314a9c0ba1910e5bb17f4 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Wed, 1 Apr 2020 18:20:03 +0900 Subject: [PATCH 02/10] update forslash test breaking changes fourslash test Temporarily retain the before fix code for easy comparison --- src/services/completions.ts | 16 ++++++++- tests/cases/fourslash/completionsJsdocTag.ts | 38 ++++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index f8db6f274d40d..1f58d7d15109f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -855,7 +855,7 @@ namespace ts.Completions { // When completion is requested without "@", we will have check to make sure that // there are no comments prefix the request position. We will only allow "*" and space. // e.g - // /** |c| /* + // /** |c| */ // // /** // |c| @@ -868,6 +868,19 @@ namespace ts.Completions { // /** // * |c| // */ + /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick + if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + return { kind: CompletionDataKind.JsDocTagName }; + } + else { + const lineStart = getLineStartPositionForPosition(position, sourceFile); + if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { + return { kind: CompletionDataKind.JsDocTag }; + } + } + /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); // jsdoc tag will be listed if there is more than one whitespace after "*" const match = /^\s*(?:[*\s]+(?=\s)|\/\*\*)?\s+(@)?$/.exec( @@ -880,6 +893,7 @@ namespace ts.Completions { kind: match[1] ? CompletionDataKind.JsDocTagName: CompletionDataKind.JsDocTag }; } + //*/ } // Completion should work inside certain JsDoc tags. For example: diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 8cfdd467ea2ec..8d3c3787dad70 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -11,32 +11,64 @@ ////function a0(s: string) {} //// +/////**@/*2*/ */ +////const some = 0; +//// + verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); // // test for src/services/completions.ts#getCompletionData.insideComment.hasDocComment (#37546) // +goTo.marker("2"); +// line 1: [/**@|c|] +// before the fix, jsdoc tag names was listed (but no longer appears +// jsdoc tag names are still listed after the fix. +// however this behavior does not by getCompletionData.insideComment.hasDocComment clause +verify.completions({ + triggerCharacter: "@", + includes: ["abstract", "access"] +}); +// line 1: [/**@|c|] -> [/**|c|] +// before the fix, jsdoc tags was listed but no longer appears +edit.backspace(1); +verify.completions({ + exact: [] +}); + +goTo.marker("1"); // line 2: [ +|c|] verify.completions({ - marker: "1", + // marker: "1", exact: [] }); // line 2: [ +|c|] -> [ +@|c|] // before the fix, jsdoc tag names was listed but no longer appears edit.insert("@"); verify.completions({ - marker: "1", + // marker: "1", // marker is invalid + triggerCharacter: "@", + exact: [] +}); + +// line 2: [ +@|c|] -> [ * ### jsdoc @|c|] +// before the fix, jsdoc tag names was listed but no longer appears +edit.replaceLine(1, " * ### jsdoc @"); +verify.completions({ + triggerCharacter: "@", exact: [] }); + // line 2: [ +@|c|] -> [ *|c|] // before the fix, jsdoc tags was listed but no longer appears edit.replaceLine(1, " *"); verify.completions({ exact: [] }); + // line 2: [ *|c|] -> [ *@|c|] -// this behavior does not by getCompletionData.insideComment.hasDocComment section +// this behavior does not by getCompletionData.insideComment.hasDocComment clause edit.insert("@"); verify.completions({ triggerCharacter: "@", From 6ad12e00211cb21138c8b52bca1106787687b74e Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Thu, 2 Apr 2020 22:32:54 +0900 Subject: [PATCH 03/10] regex --- src/services/completions.ts | 2 +- tests/cases/fourslash/completionsJsdocTag.ts | 147 ++++++++++--------- 2 files changed, 81 insertions(+), 68 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 1f58d7d15109f..cb5622fdeb573 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -883,7 +883,7 @@ namespace ts.Completions { /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); // jsdoc tag will be listed if there is more than one whitespace after "*" - const match = /^\s*(?:[*\s]+(?=\s)|\/\*\*)?\s+(@)?$/.exec( + const match = /^(?:\s*\/\*\*|[*\s]+(?=\s))?\s+(@)?$/.exec( sourceFile.text.substring(lineStart, position) ); if (match) { diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 8d3c3787dad70..78c5f7ec18876 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -5,85 +5,98 @@ //// * /**/ //// */ + +// jsdoc tags are listed when there is more than one whitespace after "*" /////** -//// +/*1*/ +//// * /*1*/ //// */ -////function a0(s: string) {} //// - -/////**@/*2*/ */ -////const some = 0; +/////** +//// * link to {/*2*/ +//// */ //// -verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); - - -// -// test for src/services/completions.ts#getCompletionData.insideComment.hasDocComment (#37546) -// -goTo.marker("2"); -// line 1: [/**@|c|] // before the fix, jsdoc tag names was listed (but no longer appears // jsdoc tag names are still listed after the fix. // however this behavior does not by getCompletionData.insideComment.hasDocComment clause -verify.completions({ - triggerCharacter: "@", - includes: ["abstract", "access"] -}); -// line 1: [/**@|c|] -> [/**|c|] +/////**@/*3*/ */ +//// +/////** +//// * @type {@/*4*/ +//// */ +//// +/////** +//// *@/*5*/ +//// */ +//// + // before the fix, jsdoc tags was listed but no longer appears -edit.backspace(1); -verify.completions({ - exact: [] -}); +/////** +//// +/*6*/ +//// */ +//// +/////** +//// */*7*/ +//// */ +//// -goTo.marker("1"); -// line 2: [ +|c|] -verify.completions({ - // marker: "1", - exact: [] -}); -// line 2: [ +|c|] -> [ +@|c|] -// before the fix, jsdoc tag names was listed but no longer appears -edit.insert("@"); -verify.completions({ - // marker: "1", // marker is invalid - triggerCharacter: "@", - exact: [] -}); +// jsdoc tag names will be listed +/////** +//// * @/*8*/ +//// */ +//// -// line 2: [ +@|c|] -> [ * ### jsdoc @|c|] // before the fix, jsdoc tag names was listed but no longer appears -edit.replaceLine(1, " * ### jsdoc @"); -verify.completions({ - triggerCharacter: "@", - exact: [] -}); +/////** +//// +@/*9*/ +//// */ +//// +/////** +//// * ### jsdoc @/*10*/ +//// */ +//// -// line 2: [ +@|c|] -> [ *|c|] -// before the fix, jsdoc tags was listed but no longer appears -edit.replaceLine(1, " *"); -verify.completions({ - exact: [] -}); +verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); -// line 2: [ *|c|] -> [ *@|c|] -// this behavior does not by getCompletionData.insideComment.hasDocComment clause -edit.insert("@"); -verify.completions({ - triggerCharacter: "@", - includes: ["abstract", "access"] -}); -// line 2: [ *@|c|] -> [ * |c|] -// jsdoc tags are listed when there is more than one whitespace after "*" -edit.replaceLine(1, " * "); -verify.completions({ - includes: ["@abstract", "@access"] -}); -// line 2: [ * |c|] -> [ * @|c|] -// jsdoc tag names will be listed -edit.insert("@"); -verify.completions({ - triggerCharacter: "@", - includes: ["abstract", "access"] + +// +// test for src/services/completions.ts#getCompletionData.insideComment.hasDocComment (#37546) +// +test.markerNames().forEach(marker => { + if (marker) { + const n = +marker; + switch (n) { + case 1: + // case 2: + verify.completions({ marker, includes: ["@abstract", "@access"] }); + break; + case 3: + // case 4: + case 5: + verify.completions({ + marker, + triggerCharacter: "@", + includes: ["abstract", "access"] + }); + break; + case 6: case 7: + verify.completions({ marker, exact: [] }); + break; + case 8: + verify.completions({ + marker, + triggerCharacter: "@", + includes: ["abstract", "access"] + }); + break; + case 9: case 10: + verify.completions({ + marker, + triggerCharacter: "@", + exact: [] + }); + break; + default: break; + } + } }); From 3336102549a2a82b31a739c2f9b69cbc14904e44 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Sun, 5 Apr 2020 00:06:50 +0900 Subject: [PATCH 04/10] fourslash test (Temporary code --- src/services/completions.ts | 1 + tests/cases/fourslash/completionsJsdocTag.ts | 189 +++++++++++++++---- 2 files changed, 155 insertions(+), 35 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index cb5622fdeb573..85b0a8f3406b3 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -876,6 +876,7 @@ namespace ts.Completions { } else { const lineStart = getLineStartPositionForPosition(position, sourceFile); + // or !/[^/\s\*]/.test(sourceFile.text.substring(lineStart, position)) if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { return { kind: CompletionDataKind.JsDocTag }; } diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 78c5f7ec18876..462de95b4bb2d 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -5,54 +5,97 @@ //// * /**/ //// */ +// cannot run fourslash test these cases because it doesn't recognize the marker +//** /*invalidMarker1*/*/ +// +//** /*invalidMarker2*/*/ +// -// jsdoc tags are listed when there is more than one whitespace after "*" +// 1x - jsdoc tags are listed when there is more than one whitespace after "*" /////** -//// * /*1*/ +//// * /*10*/ //// */ //// /////** -//// * link to {/*2*/ +//// * /*11*/ //// */ //// -// before the fix, jsdoc tag names was listed (but no longer appears -// jsdoc tag names are still listed after the fix. -// however this behavior does not by getCompletionData.insideComment.hasDocComment clause -/////**@/*3*/ */ +// 2x - also, if there is more than one whitespace at the beginning of the line. +/////** +//// /*20*/ +//// */ //// /////** -//// * @type {@/*4*/ +//// /*21*/ //// */ //// /////** -//// *@/*5*/ +//// /*22*/ //// */ //// -// before the fix, jsdoc tags was listed but no longer appears +// 3x - jsdoc tag names will be listed +/////** @/*30*/ */ +//// +/////** @/*31*/ */ +//// /////** -//// +/*6*/ +//// * @/*32*/ //// */ //// /////** -//// */*7*/ +//// * @/*33*/ +//// */ +//// +/////** +//// @/*34*/ +//// */ +//// +/////** +//// @/*35*/ +//// */ +//// +/////** +//// * @pa/*36*/ //// */ //// -// jsdoc tag names will be listed +// 4x - jsdoc tag name completions should not occur +/////**@/*40*/ */ +//// +/////** +//// *@/*41*/ +//// */ +//// /////** -//// * @/*8*/ +//// * @type {@/*42*/ +//// */ +//// +/////** +//// +@/*43*/ +//// */ +//// +/////** some description @/*44*/ */ +//// +/////** +//// * ### jsdoc @/*45*/ +//// */ +//// + +// 5x - jsdoc tag completions should not occur +/////** +//// */*50*/ //// */ //// -// before the fix, jsdoc tag names was listed but no longer appears +// also, can support the inline jsdoc tags /////** -//// +@/*9*/ +//// * link to {/*70*/ //// */ //// /////** -//// * ### jsdoc @/*10*/ +//// * link to {@/*71*/ //// */ //// @@ -64,39 +107,115 @@ verify.completions({ marker: "", includes: { name: "@property", text: "@property // test.markerNames().forEach(marker => { if (marker) { + let completionOpt: FourSlashInterface.CompletionsOptions; const n = +marker; switch (n) { - case 1: - // case 2: - verify.completions({ marker, includes: ["@abstract", "@access"] }); + /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick + + // - - - - - - + // before fix + // - - - - - - + + // jsdoc tags will be listed when there is more than one whitespace after "*" + case 10: case 11: + // also, if there is more than one whitespace at the beginning of the line. + case 20: case 21: case 22: + + // 5x - jsdoc tag completions should not occur + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // jsdoc tags will be listed but this does not the expected behavior + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case 50: + completionOpt = { marker, includes: ["@abstract", "@access"] }; break; - case 3: - // case 4: - case 5: - verify.completions({ + + // 3x - jsdoc tag names will be listed + case 30: case 31: case 32: case 33: case 34: case 35: case 36: + + // 4x - jsdoc tag name completions should not occur + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // jsdoc tag names will be listed but this does not the expected behavior + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case 40: case 41: case 42: case 43: case 44: case 45: + + // does not the expected behavior... because ts.JsDoc@jsDocTagNames is missing inline jsdoc tag name + // In other words, inline jsdoc tag is interpreted as not intending to support + case 71: + completionOpt = { marker, triggerCharacter: "@", - includes: ["abstract", "access"] - }); + includes: ["package", "param"] + }; break; - case 6: case 7: - verify.completions({ marker, exact: [] }); + /*/ + + // - - - - - - + // after fix + // - - - - - - + + // jsdoc tags will be listed when there is more than one whitespace after "*" + case 10: case 11: + // also, if there is more than one whitespace at the beginning of the line. + case 20: case 21: case 22: + + // // also, can support the inline jsdoc tags + // case 70: + completionOpt = { marker, includes: [ + "@abstract", "@access", + // "@link" + ]}; break; - case 8: - verify.completions({ + + // 3x - jsdoc tag names will be listed + case 30: case 31: case 32: case 33: case 34: case 35: + + // 4x - jsdoc tag name completions should not occur + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // this behavior does not by getCompletionData.insideComment.hasDocComment clause + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case 40: case 41: case 42: + + // // also, can support the inline jsdoc tags + // case 71: + completionOpt = { marker, triggerCharacter: "@", includes: ["abstract", "access"] - }); + }; break; - case 9: case 10: - verify.completions({ + + // 4x - jsdoc tag name completions should not occur + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // before the fix, jsdoc tag names was listed but no longer appears + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case 43: case 44: case 45: + completionOpt = { marker, triggerCharacter: "@", exact: [] - }); + }; + break; + + // 5x - jsdoc tag completions should not occur + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // before the fix, jsdoc tags was listed but no longer appears + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case 50: + completionOpt = { marker, exact: [] }; break; - default: break; + //*/ + + default: + break; + } + if (completionOpt) { + // verify.completions(completionOpt); + try { + verify.completions(completionOpt); + } catch (e) { + console.log(e.message); + console.log("please switch the code of src/services/completions.ts#getCompletionData"); + } } } }); From c4108f20c260a8312b6b8d31b189caba6405adf1 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Fri, 10 Apr 2020 20:43:00 +0900 Subject: [PATCH 05/10] regex: more restrictive in terms of jsdoc format fourslash test --- src/services/completions.ts | 2 +- tests/cases/fourslash/completionsJsdocTag.ts | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 85b0a8f3406b3..a488f7d9b0d30 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -884,7 +884,7 @@ namespace ts.Completions { /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); // jsdoc tag will be listed if there is more than one whitespace after "*" - const match = /^(?:\s*\/\*\*|[*\s]+(?=\s))?\s+(@)?$/.exec( + const match = /^(?:\s*\/\*\*|\s+\*)?\s+(@)?$/.exec( sourceFile.text.substring(lineStart, position) ); if (match) { diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 462de95b4bb2d..c11835661601c 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -5,11 +5,6 @@ //// * /**/ //// */ -// cannot run fourslash test these cases because it doesn't recognize the marker -//** /*invalidMarker1*/*/ -// -//** /*invalidMarker2*/*/ -// // 1x - jsdoc tags are listed when there is more than one whitespace after "*" /////** @@ -162,12 +157,11 @@ test.markerNames().forEach(marker => { // case 70: completionOpt = { marker, includes: [ "@abstract", "@access", - // "@link" ]}; break; // 3x - jsdoc tag names will be listed - case 30: case 31: case 32: case 33: case 34: case 35: + case 30: case 31: case 32: case 33: case 34: case 35: case 36: // 4x - jsdoc tag name completions should not occur // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -180,7 +174,7 @@ test.markerNames().forEach(marker => { completionOpt = { marker, triggerCharacter: "@", - includes: ["abstract", "access"] + includes: ["package", "param"] }; break; From ada017ee3b3f0bbbc45ac84c31810cafd5255516 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Fri, 10 Apr 2020 21:23:00 +0900 Subject: [PATCH 06/10] regex: max indent restriction --- src/services/completions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index a488f7d9b0d30..d417b10205170 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -884,7 +884,7 @@ namespace ts.Completions { /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); // jsdoc tag will be listed if there is more than one whitespace after "*" - const match = /^(?:\s*\/\*\*|\s+\*)?\s+(@)?$/.exec( + const match = /^(?:\s{0,400}\/\*\*|\s{1,401}\*)?\s+(@)?$/.exec( sourceFile.text.substring(lineStart, position) ); if (match) { From 92ac5cb7faa28a2bab38ba1c839788e894990c44 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Sat, 11 Apr 2020 22:56:22 +0900 Subject: [PATCH 07/10] achieved goal by partial match strategy (probably --- src/services/completions.ts | 14 +++--- tests/cases/fourslash/completionInJsDoc.ts | 4 +- tests/cases/fourslash/completionsJsdocTag.ts | 48 ++++++++++++-------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index d417b10205170..5f3a8b74804a7 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -883,14 +883,11 @@ namespace ts.Completions { } /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); - // jsdoc tag will be listed if there is more than one whitespace after "*" - const match = /^(?:\s{0,400}\/\*\*|\s{1,401}\*)?\s+(@)?$/.exec( - sourceFile.text.substring(lineStart, position) - ); - if (match) { + const jsdocFragment = sourceFile.text.substring(lineStart, position); + const reJSDocFragment = /^(?:\s*\/\*\*\s+|\s+\*?\s+)(@(?:\w+)?)?/g; + const match = reJSDocFragment.exec(jsdocFragment); + if (match && reJSDocFragment.lastIndex === jsdocFragment.length) { return { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names kind: match[1] ? CompletionDataKind.JsDocTagName: CompletionDataKind.JsDocTag }; } @@ -902,9 +899,12 @@ namespace ts.Completions { // Completion should work in the brackets const tag = getJsDocTagAtPosition(currentToken, position); if (tag) { + /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick if (tag.tagName.pos <= position && position <= tag.tagName.end) { return { kind: CompletionDataKind.JsDocTagName }; } + /*/ + //*/ if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) { currentToken = getTokenAtPosition(sourceFile, position); if (!currentToken || diff --git a/tests/cases/fourslash/completionInJsDoc.ts b/tests/cases/fourslash/completionInJsDoc.ts index d30a92fe114ba..8b3338fcbfc0c 100644 --- a/tests/cases/fourslash/completionInJsDoc.ts +++ b/tests/cases/fourslash/completionInJsDoc.ts @@ -29,8 +29,8 @@ //// /** /*9*/ */ //// //// /** -//// /*10*/ -//// */ +//// /*10*/ +//// */ //// //// /** //// * /*11*/ diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index c11835661601c..2e641d2e462b7 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -16,17 +16,13 @@ //// */ //// -// 2x - also, if there is more than one whitespace at the beginning of the line. +// 2x - Also, if there are two or more blanks at the beginning of the line /////** -//// /*20*/ +//// /*20*/ //// */ //// /////** -//// /*21*/ -//// */ -//// -/////** -//// /*22*/ +//// /*21*/ //// */ //// @@ -77,12 +73,24 @@ //// * ### jsdoc @/*45*/ //// */ //// +/////** +////@/*46*/ +//// */ +//// // 5x - jsdoc tag completions should not occur /////** //// */*50*/ //// */ //// +/////** +//// /*51*/ +//// */ +//// +/////** +/////*52*/ +//// */ +//// // also, can support the inline jsdoc tags /////** @@ -113,14 +121,14 @@ test.markerNames().forEach(marker => { // jsdoc tags will be listed when there is more than one whitespace after "*" case 10: case 11: - // also, if there is more than one whitespace at the beginning of the line. - case 20: case 21: case 22: + // Also, if there are two or more blanks at the beginning of the line + case 20: case 21: // 5x - jsdoc tag completions should not occur // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // jsdoc tags will be listed but this does not the expected behavior // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 50: + case 50: case 51: case 52: completionOpt = { marker, includes: ["@abstract", "@access"] }; break; @@ -131,7 +139,7 @@ test.markerNames().forEach(marker => { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // jsdoc tag names will be listed but this does not the expected behavior // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 40: case 41: case 42: case 43: case 44: case 45: + case 40: case 41: case 42: case 43: case 44: case 45: case 46: // does not the expected behavior... because ts.JsDoc@jsDocTagNames is missing inline jsdoc tag name // In other words, inline jsdoc tag is interpreted as not intending to support @@ -150,8 +158,8 @@ test.markerNames().forEach(marker => { // jsdoc tags will be listed when there is more than one whitespace after "*" case 10: case 11: - // also, if there is more than one whitespace at the beginning of the line. - case 20: case 21: case 22: + // Also, if there are two or more blanks at the beginning of the line + case 20: case 21: // // also, can support the inline jsdoc tags // case 70: @@ -163,11 +171,11 @@ test.markerNames().forEach(marker => { // 3x - jsdoc tag names will be listed case 30: case 31: case 32: case 33: case 34: case 35: case 36: - // 4x - jsdoc tag name completions should not occur - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // this behavior does not by getCompletionData.insideComment.hasDocComment clause - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 40: case 41: case 42: + // // 4x - jsdoc tag name completions should not occur + // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // // this behavior does not by getCompletionData.insideComment.hasDocComment clause + // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // case 40: case 41: case 42: // // also, can support the inline jsdoc tags // case 71: @@ -182,7 +190,7 @@ test.markerNames().forEach(marker => { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // before the fix, jsdoc tag names was listed but no longer appears // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 43: case 44: case 45: + case 40: case 41: case 42: case 43: case 44: case 45: case 46: completionOpt = { marker, triggerCharacter: "@", @@ -194,7 +202,7 @@ test.markerNames().forEach(marker => { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // before the fix, jsdoc tags was listed but no longer appears // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 50: + case 50: case 51: case 52: completionOpt = { marker, exact: [] }; break; //*/ From 8c58df30a2c8881be50393bbd66d3902f3c79287 Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Sat, 11 Apr 2020 23:53:40 +0900 Subject: [PATCH 08/10] cleanup --- src/services/completions.ts | 27 ++----- tests/cases/fourslash/completionsJsdocTag.ts | 74 +------------------- 2 files changed, 6 insertions(+), 95 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 5f3a8b74804a7..28c79ad9bdcc0 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -868,30 +868,19 @@ namespace ts.Completions { // /** // * |c| // */ - /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick - if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - return { kind: CompletionDataKind.JsDocTagName }; - } - else { - const lineStart = getLineStartPositionForPosition(position, sourceFile); - // or !/[^/\s\*]/.test(sourceFile.text.substring(lineStart, position)) - if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { - return { kind: CompletionDataKind.JsDocTag }; - } - } - /*/ const lineStart = getLineStartPositionForPosition(position, sourceFile); const jsdocFragment = sourceFile.text.substring(lineStart, position); const reJSDocFragment = /^(?:\s*\/\*\*\s+|\s+\*?\s+)(@(?:\w+)?)?/g; const match = reJSDocFragment.exec(jsdocFragment); if (match && reJSDocFragment.lastIndex === jsdocFragment.length) { return { - kind: match[1] ? CompletionDataKind.JsDocTagName: CompletionDataKind.JsDocTag + kind: match[1] + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + ? CompletionDataKind.JsDocTagName: + CompletionDataKind.JsDocTag }; } - //*/ } // Completion should work inside certain JsDoc tags. For example: @@ -899,12 +888,6 @@ namespace ts.Completions { // Completion should work in the brackets const tag = getJsDocTagAtPosition(currentToken, position); if (tag) { - /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick - if (tag.tagName.pos <= position && position <= tag.tagName.end) { - return { kind: CompletionDataKind.JsDocTagName }; - } - /*/ - //*/ if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) { currentToken = getTokenAtPosition(sourceFile, position); if (!currentToken || diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 2e641d2e462b7..59700257d1916 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -92,16 +92,6 @@ //// */ //// -// also, can support the inline jsdoc tags -/////** -//// * link to {/*70*/ -//// */ -//// -/////** -//// * link to {@/*71*/ -//// */ -//// - verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); @@ -113,56 +103,10 @@ test.markerNames().forEach(marker => { let completionOpt: FourSlashInterface.CompletionsOptions; const n = +marker; switch (n) { - /* https://coderwall.com/p/zbc2zw/the-comment-toggle-trick - - // - - - - - - - // before fix - // - - - - - - - // jsdoc tags will be listed when there is more than one whitespace after "*" case 10: case 11: // Also, if there are two or more blanks at the beginning of the line case 20: case 21: - - // 5x - jsdoc tag completions should not occur - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // jsdoc tags will be listed but this does not the expected behavior - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 50: case 51: case 52: - completionOpt = { marker, includes: ["@abstract", "@access"] }; - break; - - // 3x - jsdoc tag names will be listed - case 30: case 31: case 32: case 33: case 34: case 35: case 36: - - // 4x - jsdoc tag name completions should not occur - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // jsdoc tag names will be listed but this does not the expected behavior - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 40: case 41: case 42: case 43: case 44: case 45: case 46: - - // does not the expected behavior... because ts.JsDoc@jsDocTagNames is missing inline jsdoc tag name - // In other words, inline jsdoc tag is interpreted as not intending to support - case 71: - completionOpt = { - marker, - triggerCharacter: "@", - includes: ["package", "param"] - }; - break; - /*/ - - // - - - - - - - // after fix - // - - - - - - - - // jsdoc tags will be listed when there is more than one whitespace after "*" - case 10: case 11: - // Also, if there are two or more blanks at the beginning of the line - case 20: case 21: - - // // also, can support the inline jsdoc tags - // case 70: completionOpt = { marker, includes: [ "@abstract", "@access", ]}; @@ -170,15 +114,6 @@ test.markerNames().forEach(marker => { // 3x - jsdoc tag names will be listed case 30: case 31: case 32: case 33: case 34: case 35: case 36: - - // // 4x - jsdoc tag name completions should not occur - // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // this behavior does not by getCompletionData.insideComment.hasDocComment clause - // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // case 40: case 41: case 42: - - // // also, can support the inline jsdoc tags - // case 71: completionOpt = { marker, triggerCharacter: "@", @@ -205,19 +140,12 @@ test.markerNames().forEach(marker => { case 50: case 51: case 52: completionOpt = { marker, exact: [] }; break; - //*/ default: break; } if (completionOpt) { - // verify.completions(completionOpt); - try { - verify.completions(completionOpt); - } catch (e) { - console.log(e.message); - console.log("please switch the code of src/services/completions.ts#getCompletionData"); - } + verify.completions(completionOpt); } } }); From fe460f0a899e32bc848c2c28072ef15ef504fe8e Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Wed, 29 Apr 2020 22:21:55 +0900 Subject: [PATCH 09/10] apply requested changes --- src/services/completions.ts | 11 +++--- tests/cases/fourslash/completionsJsdocTag.ts | 38 -------------------- 2 files changed, 7 insertions(+), 42 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 28c79ad9bdcc0..55c78b3d5aeb0 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -875,10 +875,10 @@ namespace ts.Completions { if (match && reJSDocFragment.lastIndex === jsdocFragment.length) { return { kind: match[1] - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - ? CompletionDataKind.JsDocTagName: - CompletionDataKind.JsDocTag + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + ? CompletionDataKind.JsDocTagName + : CompletionDataKind.JsDocTag }; } } @@ -888,6 +888,9 @@ namespace ts.Completions { // Completion should work in the brackets const tag = getJsDocTagAtPosition(currentToken, position); if (tag) { + if (tag.tagName.pos <= position && position <= tag.tagName.end) { + return { kind: CompletionDataKind.JsDocTagName }; + } if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) { currentToken = getTokenAtPosition(sourceFile, position); if (!currentToken || diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index 59700257d1916..f4332afd11a2e 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -52,32 +52,6 @@ //// */ //// -// 4x - jsdoc tag name completions should not occur -/////**@/*40*/ */ -//// -/////** -//// *@/*41*/ -//// */ -//// -/////** -//// * @type {@/*42*/ -//// */ -//// -/////** -//// +@/*43*/ -//// */ -//// -/////** some description @/*44*/ */ -//// -/////** -//// * ### jsdoc @/*45*/ -//// */ -//// -/////** -////@/*46*/ -//// */ -//// - // 5x - jsdoc tag completions should not occur /////** //// */*50*/ @@ -121,18 +95,6 @@ test.markerNames().forEach(marker => { }; break; - // 4x - jsdoc tag name completions should not occur - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // before the fix, jsdoc tag names was listed but no longer appears - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 40: case 41: case 42: case 43: case 44: case 45: case 46: - completionOpt = { - marker, - triggerCharacter: "@", - exact: [] - }; - break; - // 5x - jsdoc tag completions should not occur // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // before the fix, jsdoc tags was listed but no longer appears From 3f1bb2d05287a56ba1b0725f796b77d76f57bd3b Mon Sep 17 00:00:00 2001 From: jeffy-g Date: Mon, 11 May 2020 20:54:27 +0900 Subject: [PATCH 10/10] Change to a version with minimal modifications --- src/services/completions.ts | 54 +++++----- tests/cases/fourslash/completionInJsDoc.ts | 4 +- tests/cases/fourslash/completionsJsdocTag.ts | 105 ------------------- 3 files changed, 28 insertions(+), 135 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 55c78b3d5aeb0..a3845bf3ece03 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -852,34 +852,32 @@ namespace ts.Completions { let isInSnippetScope = false; if (insideComment) { if (hasDocComment(sourceFile, position)) { - // When completion is requested without "@", we will have check to make sure that - // there are no comments prefix the request position. We will only allow "*" and space. - // e.g - // /** |c| */ - // - // /** - // |c| - // */ - // - // /** - // * |c| - // */ - // - // /** - // * |c| - // */ - const lineStart = getLineStartPositionForPosition(position, sourceFile); - const jsdocFragment = sourceFile.text.substring(lineStart, position); - const reJSDocFragment = /^(?:\s*\/\*\*\s+|\s+\*?\s+)(@(?:\w+)?)?/g; - const match = reJSDocFragment.exec(jsdocFragment); - if (match && reJSDocFragment.lastIndex === jsdocFragment.length) { - return { - kind: match[1] - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - ? CompletionDataKind.JsDocTagName - : CompletionDataKind.JsDocTag - }; + if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + return { kind: CompletionDataKind.JsDocTagName }; + } + else { + // When completion is requested without "@", we will have check to make sure that + // there are no comments prefix the request position. We will only allow "*" and space. + // e.g + // /** |c| /* + // + // /** + // |c| + // */ + // + // /** + // * |c| + // */ + // + // /** + // * |c| + // */ + const lineStart = getLineStartPositionForPosition(position, sourceFile); + if (!/[^\*|\s(/)]/.test(sourceFile.text.substring(lineStart, position))) { + return { kind: CompletionDataKind.JsDocTag }; + } } } diff --git a/tests/cases/fourslash/completionInJsDoc.ts b/tests/cases/fourslash/completionInJsDoc.ts index 8b3338fcbfc0c..d30a92fe114ba 100644 --- a/tests/cases/fourslash/completionInJsDoc.ts +++ b/tests/cases/fourslash/completionInJsDoc.ts @@ -29,8 +29,8 @@ //// /** /*9*/ */ //// //// /** -//// /*10*/ -//// */ +//// /*10*/ +//// */ //// //// /** //// * /*11*/ diff --git a/tests/cases/fourslash/completionsJsdocTag.ts b/tests/cases/fourslash/completionsJsdocTag.ts index f4332afd11a2e..71a7a97bc6e61 100644 --- a/tests/cases/fourslash/completionsJsdocTag.ts +++ b/tests/cases/fourslash/completionsJsdocTag.ts @@ -5,109 +5,4 @@ //// * /**/ //// */ - -// 1x - jsdoc tags are listed when there is more than one whitespace after "*" -/////** -//// * /*10*/ -//// */ -//// -/////** -//// * /*11*/ -//// */ -//// - -// 2x - Also, if there are two or more blanks at the beginning of the line -/////** -//// /*20*/ -//// */ -//// -/////** -//// /*21*/ -//// */ -//// - -// 3x - jsdoc tag names will be listed -/////** @/*30*/ */ -//// -/////** @/*31*/ */ -//// -/////** -//// * @/*32*/ -//// */ -//// -/////** -//// * @/*33*/ -//// */ -//// -/////** -//// @/*34*/ -//// */ -//// -/////** -//// @/*35*/ -//// */ -//// -/////** -//// * @pa/*36*/ -//// */ -//// - -// 5x - jsdoc tag completions should not occur -/////** -//// */*50*/ -//// */ -//// -/////** -//// /*51*/ -//// */ -//// -/////** -/////*52*/ -//// */ -//// - verify.completions({ marker: "", includes: { name: "@property", text: "@property", kind: "keyword" } }); - - -// -// test for src/services/completions.ts#getCompletionData.insideComment.hasDocComment (#37546) -// -test.markerNames().forEach(marker => { - if (marker) { - let completionOpt: FourSlashInterface.CompletionsOptions; - const n = +marker; - switch (n) { - // jsdoc tags will be listed when there is more than one whitespace after "*" - case 10: case 11: - // Also, if there are two or more blanks at the beginning of the line - case 20: case 21: - completionOpt = { marker, includes: [ - "@abstract", "@access", - ]}; - break; - - // 3x - jsdoc tag names will be listed - case 30: case 31: case 32: case 33: case 34: case 35: case 36: - completionOpt = { - marker, - triggerCharacter: "@", - includes: ["package", "param"] - }; - break; - - // 5x - jsdoc tag completions should not occur - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // before the fix, jsdoc tags was listed but no longer appears - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case 50: case 51: case 52: - completionOpt = { marker, exact: [] }; - break; - - default: - break; - } - if (completionOpt) { - verify.completions(completionOpt); - } - } -});