Skip to content

Commit 8e86b24

Browse files
authored
feat(40233): add JS Doc types to smart selection (microsoft#40338)
1 parent dc8952d commit 8e86b24

21 files changed

+426
-10
lines changed

src/services/smartSelection.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace ts.SmartSelectionRange {
1313
const prevNode: Node | undefined = children[i - 1];
1414
const node: Node = children[i];
1515
const nextNode: Node | undefined = children[i + 1];
16-
if (node.getStart(sourceFile) > pos) {
16+
if (getTokenPosOfNode(node, sourceFile, /*includeJsDoc*/ true) > pos) {
1717
break outer;
1818
}
1919

@@ -23,14 +23,14 @@ namespace ts.SmartSelectionRange {
2323
// of things that should be considered independently.
2424
// 3. A VariableStatement’s children are just a VaraiableDeclarationList and a semicolon.
2525
// 4. A lone VariableDeclaration in a VaraibleDeclaration feels redundant with the VariableStatement.
26-
//
2726
// Dive in without pushing a selection range.
2827
if (isBlock(node)
2928
|| isTemplateSpan(node) || isTemplateHead(node) || isTemplateTail(node)
3029
|| prevNode && isTemplateHead(prevNode)
3130
|| isVariableDeclarationList(node) && isVariableStatement(parentNode)
3231
|| isSyntaxList(node) && isVariableDeclarationList(parentNode)
33-
|| isVariableDeclaration(node) && isSyntaxList(parentNode) && children.length === 1) {
32+
|| isVariableDeclaration(node) && isSyntaxList(parentNode) && children.length === 1
33+
|| isJSDocTypeExpression(node) || isJSDocSignature(node) || isJSDocTypeLiteral(node)) {
3434
parentNode = node;
3535
break;
3636
}
@@ -44,16 +44,15 @@ namespace ts.SmartSelectionRange {
4444

4545
// Blocks with braces, brackets, parens, or JSX tags on separate lines should be
4646
// selected from open to close, including whitespace but not including the braces/etc. themselves.
47-
const isBetweenMultiLineBookends = isSyntaxList(node)
48-
&& isListOpener(prevNode)
49-
&& isListCloser(nextNode)
47+
const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode)
5048
&& !positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile);
51-
const jsDocCommentStart = hasJSDocNodes(node) && node.jsDoc![0].getStart();
5249
const start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart();
53-
const end = isBetweenMultiLineBookends ? nextNode.getStart() : node.getEnd();
54-
if (isNumber(jsDocCommentStart)) {
55-
pushSelectionRange(jsDocCommentStart, end);
50+
const end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node);
51+
52+
if (hasJSDocNodes(node) && node.jsDoc?.length) {
53+
pushSelectionRange(first(node.jsDoc).getStart(), end);
5654
}
55+
5756
pushSelectionRange(start, end);
5857

5958
// String literals should have a stop both inside and outside their quotes.
@@ -270,4 +269,17 @@ namespace ts.SmartSelectionRange {
270269
|| kind === SyntaxKind.CloseParenToken
271270
|| kind === SyntaxKind.JsxClosingElement;
272271
}
272+
273+
function getEndPos(sourceFile: SourceFile, node: Node): number {
274+
switch (node.kind) {
275+
case SyntaxKind.JSDocParameterTag:
276+
case SyntaxKind.JSDocCallbackTag:
277+
case SyntaxKind.JSDocPropertyTag:
278+
case SyntaxKind.JSDocTypedefTag:
279+
case SyntaxKind.JSDocThisTag:
280+
return sourceFile.getLineEndOfPosition(node.getStart());
281+
default:
282+
return node.getEnd();
283+
}
284+
}
273285
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @returns {Array<{ value: /**/string }>}
3+
*/
4+
function foo() { return [] }
5+
6+
7+
string
8+
9+
10+
value: string
11+
12+
13+
{ value: string }
14+
15+
16+
Array<{ value: string }>
17+
18+
19+
@returns {Array<{ value: string }>}
20+
21+
22+
/**
23+
* @returns {Array<{ value: string }>}
24+
*/
25+
26+
27+
/**
28+
* @returns {Array<{ value: string }>}
29+
*/
30+
function foo() { return [] }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @template T
3+
* @extends {/**/Set<T>}
4+
*/
5+
class A extends B {
6+
}
7+
8+
9+
Set
10+
11+
12+
Set<T>
13+
14+
15+
@extends {Set<T>}
16+
17+
18+
/**
19+
* @template T
20+
* @extends {Set<T>}
21+
*/
22+
23+
24+
/**
25+
* @template T
26+
* @extends {Set<T>}
27+
*/
28+
class A extends B {
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @type {/**/string}
3+
*/
4+
const foo;
5+
6+
7+
string
8+
9+
10+
@type {string}
11+
12+
13+
/**
14+
* @type {string}
15+
*/
16+
17+
18+
/**
19+
* @type {string}
20+
*/
21+
const foo;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @param {/**/string} x
3+
*/
4+
function foo(x) {}
5+
6+
7+
string
8+
9+
10+
@param {string} x
11+
12+
13+
/**
14+
* @param {string} x
15+
*/
16+
17+
18+
/**
19+
* @param {string} x
20+
*/
21+
function foo(x) {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @typedef {object} Foo
3+
* @property {string} a
4+
* @property {number} b
5+
* @property {/**/number} c
6+
*/
7+
8+
/** @type {Foo} */
9+
const foo;
10+
11+
12+
number
13+
14+
15+
@property {number} c
16+
17+
18+
/**
19+
* @typedef {object} Foo
20+
* @property {string} a
21+
* @property {number} b
22+
* @property {number} c
23+
*/
24+
25+
26+
/**
27+
* @typedef {object} Foo
28+
* @property {string} a
29+
* @property {number} b
30+
* @property {number} c
31+
*/
32+
33+
/** @type {Foo} */
34+
const foo;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @callback Foo
3+
* @param {string} data
4+
* @param {/**/number} [index] - comment
5+
* @return {boolean}
6+
*/
7+
8+
/** @type {Foo} */
9+
const foo = s => !(s.length % 2);
10+
11+
12+
number
13+
14+
15+
@param {number} [index] - comment
16+
17+
18+
/**
19+
* @callback Foo
20+
* @param {string} data
21+
* @param {number} [index] - comment
22+
* @return {boolean}
23+
*/
24+
25+
26+
/**
27+
* @callback Foo
28+
* @param {string} data
29+
* @param {number} [index] - comment
30+
* @return {boolean}
31+
*/
32+
33+
/** @type {Foo} */
34+
const foo = s => !(s.length % 2);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @template T
3+
* @param {/**/T} x
4+
* @return {T}
5+
*/
6+
function foo(x) {
7+
return x;
8+
}
9+
10+
11+
T
12+
13+
14+
@param {T} x
15+
16+
17+
/**
18+
* @template T
19+
* @param {T} x
20+
* @return {T}
21+
*/
22+
23+
24+
/**
25+
* @template T
26+
* @param {T} x
27+
* @return {T}
28+
*/
29+
function foo(x) {
30+
return x;
31+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @constructor
3+
* @param {/**/number} data
4+
*/
5+
function Foo(data) {
6+
}
7+
8+
9+
number
10+
11+
12+
@param {number} data
13+
14+
15+
/**
16+
* @constructor
17+
* @param {number} data
18+
*/
19+
20+
21+
/**
22+
* @constructor
23+
* @param {number} data
24+
*/
25+
function Foo(data) {
26+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @this {/**/Foo}
3+
* @param {*} e
4+
*/
5+
function callback(e) {
6+
}
7+
8+
9+
Foo
10+
11+
12+
@this {Foo}
13+
14+
15+
/**
16+
* @this {Foo}
17+
* @param {*} e
18+
*/
19+
20+
21+
/**
22+
* @this {Foo}
23+
* @param {*} e
24+
*/
25+
function callback(e) {
26+
}
27+
28+
================================================================================
29+
30+
/**
31+
* @this {Foo}
32+
* @param {/**/*} e
33+
*/
34+
function callback(e) {
35+
}
36+
37+
38+
*
39+
40+
41+
@param {*} e
42+
43+
44+
/**
45+
* @this {Foo}
46+
* @param {*} e
47+
*/
48+
49+
50+
/**
51+
* @this {Foo}
52+
* @param {*} e
53+
*/
54+
function callback(e) {
55+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/** @enum {/**/number} */
2+
const Foo = {
3+
x: 0,
4+
y: 1,
5+
};
6+
7+
8+
number
9+
10+
11+
@enum {number}
12+
13+
14+
/** @enum {number} */
15+
16+
17+
/** @enum {number} */
18+
const Foo = {
19+
x: 0,
20+
y: 1,
21+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
/////**
4+
//// * @returns {Array<{ value: /**/string }>}
5+
//// */
6+
////function foo() { return [] }
7+
8+
verify.baselineSmartSelection();

0 commit comments

Comments
 (0)