Skip to content

Commit 8e6e87f

Browse files
authored
πŸ› Fix smart selection of propery signatures having JSDoc comments (#49804)
* πŸ› Avoid grouping JSDoc nodes of propery signatures with others in smart selection Signed-off-by: Babak K. Shandiz <babak.k.shandiz@gmail.com> * βš—οΈ Add test case for JSDoc smart selection (#39618) Signed-off-by: Babak K. Shandiz <babak.k.shandiz@gmail.com> * βš—οΈ Add test baseline for JSDoc smart selection (#39618) Signed-off-by: Babak K. Shandiz <babak.k.shandiz@gmail.com> * πŸ› Fix skipping SyntaxList first child's JSDoc in smart selection Signed-off-by: GitHub <noreply@github.com> * βš—οΈ Add tests to ensure not skipping first SyntaxList child's JSDoc Signed-off-by: GitHub <noreply@github.com> * πŸ”¨ Exclude JSDoc token from tokens pivoting property signature Signed-off-by: GitHub <noreply@github.com> * βš—οΈ Update test case to also include modifier Signed-off-by: GitHub <noreply@github.com> * βš—οΈ Update test case reference baseline Signed-off-by: GitHub <noreply@github.com>
1 parent 1260081 commit 8e6e87f

7 files changed

+388
-2
lines changed

β€Žsrc/services/smartSelection.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,24 @@ namespace ts.SmartSelectionRange {
5252
// selected from open to close, including whitespace but not including the braces/etc. themselves.
5353
const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode)
5454
&& !positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile);
55-
const start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart();
55+
let start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart();
5656
const end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node);
5757

5858
if (hasJSDocNodes(node) && node.jsDoc?.length) {
5959
pushSelectionRange(first(node.jsDoc).getStart(), end);
6060
}
6161

62+
// (#39618 & #49807)
63+
// When the node is a SyntaxList and its first child has a JSDoc comment, then the node's
64+
// `start` (which usually is the result of calling `node.getStart()`) points to the first
65+
// token after the JSDoc comment. So, we have to make sure we'd pushed the selection
66+
// covering the JSDoc comment before diving further.
67+
if (isSyntaxList(node)) {
68+
const firstChild = node.getChildren()[0];
69+
if (firstChild && hasJSDocNodes(firstChild) && firstChild.jsDoc?.length && firstChild.getStart() !== node.pos) {
70+
start = Math.min(start, first(firstChild.jsDoc).getStart());
71+
}
72+
}
6273
pushSelectionRange(start, end);
6374

6475
// String literals should have a stop both inside and outside their quotes.
@@ -184,7 +195,10 @@ namespace ts.SmartSelectionRange {
184195
if (isPropertySignature(node)) {
185196
const children = groupChildren(node.getChildren(), child =>
186197
child === node.name || contains(node.modifiers, child));
187-
return splitChildren(children, ({ kind }) => kind === SyntaxKind.ColonToken);
198+
const firstJSDocChild = children[0]?.kind === SyntaxKind.JSDoc ? children[0] : undefined;
199+
const withJSDocSeparated = firstJSDocChild? children.slice(1) : children;
200+
const splittedChildren = splitChildren(withJSDocSeparated, ({ kind }) => kind === SyntaxKind.ColonToken);
201+
return firstJSDocChild? [firstJSDocChild, createSyntaxList(splittedChildren)] : splittedChildren;
188202
}
189203

190204
// Group the parameter name with its `...`, then that group with its `?`, then pivot on `=`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
const x = 1;
2+
type Foo = {
3+
/** comment */
4+
/**/readonly status: number;
5+
};
6+
7+
8+
readonly
9+
10+
11+
readonly status
12+
13+
14+
readonly status: number;
15+
16+
17+
/** comment */
18+
readonly status: number;
19+
20+
21+
↲
22+
β€’β€’/** comment */
23+
readonly status: number;↲
24+
25+
26+
{
27+
/** comment */
28+
readonly status: number;
29+
}
30+
31+
type Foo = {
32+
/** comment */
33+
readonly status: number;
34+
};
35+
36+
const x = 1;
37+
type Foo = {
38+
/** comment */
39+
readonly status: number;
40+
};
41+
42+
================================================================================
43+
44+
const x = 1;
45+
type Foo = {
46+
/** comment */
47+
readonly /**/status: number;
48+
};
49+
50+
51+
status
52+
53+
54+
readonly status
55+
56+
57+
readonly status: number;
58+
59+
60+
/** comment */
61+
readonly status: number;
62+
63+
64+
↲
65+
β€’β€’/** comment */
66+
readonly status: number;↲
67+
68+
69+
{
70+
/** comment */
71+
readonly status: number;
72+
}
73+
74+
type Foo = {
75+
/** comment */
76+
readonly status: number;
77+
};
78+
79+
const x = 1;
80+
type Foo = {
81+
/** comment */
82+
readonly status: number;
83+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
type B = {};
2+
type A = {
3+
a(/** Comment */ /**/p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
4+
};
5+
6+
7+
p0
8+
9+
10+
p0: number
11+
12+
13+
/** Comment */ p0: number
14+
15+
16+
/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number
17+
18+
19+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
20+
21+
22+
↲
23+
β€’β€’β€’β€’a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;↲
24+
25+
26+
{
27+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
28+
}
29+
30+
type A = {
31+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
32+
};
33+
34+
type B = {};
35+
type A = {
36+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
37+
};
38+
39+
================================================================================
40+
41+
type B = {};
42+
type A = {
43+
a(/** Comment */ p0: number, /** Comment */ /**/p1: number, /** Comment */ p2: number): string;
44+
};
45+
46+
47+
p1
48+
49+
50+
p1: number
51+
52+
53+
/** Comment */ p1: number
54+
55+
56+
/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number
57+
58+
59+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
60+
61+
62+
↲
63+
β€’β€’β€’β€’a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;↲
64+
65+
66+
{
67+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
68+
}
69+
70+
type A = {
71+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
72+
};
73+
74+
type B = {};
75+
type A = {
76+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
77+
};
78+
79+
================================================================================
80+
81+
type B = {};
82+
type A = {
83+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ /**/p2: number): string;
84+
};
85+
86+
87+
p2
88+
89+
90+
p2: number
91+
92+
93+
/** Comment */ p2: number
94+
95+
96+
/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number
97+
98+
99+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
100+
101+
102+
↲
103+
β€’β€’β€’β€’a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;↲
104+
105+
106+
{
107+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
108+
}
109+
110+
type A = {
111+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
112+
};
113+
114+
type B = {};
115+
type A = {
116+
a(/** Comment */ p0: number, /** Comment */ p1: number, /** Comment */ p2: number): string;
117+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
let a;
2+
let b: {
3+
/** Comment */ /**/p0: number
4+
/** Comment */ p1: number
5+
/** Comment */ p2: number
6+
};
7+
let c;
8+
9+
10+
p0
11+
12+
13+
p0: number
14+
15+
16+
/** Comment */ p0: number
17+
18+
19+
↲
20+
β€’β€’β€’β€’/** Comment */ p0: number
21+
/** Comment */ p1: number
22+
/** Comment */ p2: number↲
23+
24+
25+
{
26+
/** Comment */ p0: number
27+
/** Comment */ p1: number
28+
/** Comment */ p2: number
29+
}
30+
31+
32+
let b: {
33+
/** Comment */ p0: number
34+
/** Comment */ p1: number
35+
/** Comment */ p2: number
36+
};
37+
38+
39+
let a;
40+
let b: {
41+
/** Comment */ p0: number
42+
/** Comment */ p1: number
43+
/** Comment */ p2: number
44+
};
45+
let c;
46+
47+
================================================================================
48+
49+
let a;
50+
let b: {
51+
/** Comment */ p0: number
52+
/** Comment */ /**/p1: number
53+
/** Comment */ p2: number
54+
};
55+
let c;
56+
57+
58+
p1
59+
60+
61+
p1: number
62+
63+
64+
/** Comment */ p1: number
65+
66+
67+
↲
68+
β€’β€’β€’β€’/** Comment */ p0: number
69+
/** Comment */ p1: number
70+
/** Comment */ p2: number↲
71+
72+
73+
{
74+
/** Comment */ p0: number
75+
/** Comment */ p1: number
76+
/** Comment */ p2: number
77+
}
78+
79+
80+
let b: {
81+
/** Comment */ p0: number
82+
/** Comment */ p1: number
83+
/** Comment */ p2: number
84+
};
85+
86+
87+
let a;
88+
let b: {
89+
/** Comment */ p0: number
90+
/** Comment */ p1: number
91+
/** Comment */ p2: number
92+
};
93+
let c;
94+
95+
================================================================================
96+
97+
let a;
98+
let b: {
99+
/** Comment */ p0: number
100+
/** Comment */ p1: number
101+
/** Comment */ /**/p2: number
102+
};
103+
let c;
104+
105+
106+
p2
107+
108+
109+
p2: number
110+
111+
112+
/** Comment */ p2: number
113+
114+
115+
↲
116+
β€’β€’β€’β€’/** Comment */ p0: number
117+
/** Comment */ p1: number
118+
/** Comment */ p2: number↲
119+
120+
121+
{
122+
/** Comment */ p0: number
123+
/** Comment */ p1: number
124+
/** Comment */ p2: number
125+
}
126+
127+
128+
let b: {
129+
/** Comment */ p0: number
130+
/** Comment */ p1: number
131+
/** Comment */ p2: number
132+
};
133+
134+
135+
let a;
136+
let b: {
137+
/** Comment */ p0: number
138+
/** Comment */ p1: number
139+
/** Comment */ p2: number
140+
};
141+
let c;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////const x = 1;
4+
////type Foo = {
5+
//// /** comment */
6+
//// /*2*/readonly /*1*/status: number;
7+
////};
8+
9+
// https://github.com/microsoft/TypeScript/issues/39618
10+
verify.baselineSmartSelection();

0 commit comments

Comments
Β (0)