feat(40233): add JS Doc types to smart selection (#40338)

This commit is contained in:
Alex T
2020-09-25 12:36:04 -07:00
committed by GitHub
parent dc8952d308
commit 8e86b24036
21 changed files with 426 additions and 10 deletions
+22 -10
View File
@@ -13,7 +13,7 @@ namespace ts.SmartSelectionRange {
const prevNode: Node | undefined = children[i - 1];
const node: Node = children[i];
const nextNode: Node | undefined = children[i + 1];
if (node.getStart(sourceFile) > pos) {
if (getTokenPosOfNode(node, sourceFile, /*includeJsDoc*/ true) > pos) {
break outer;
}
@@ -23,14 +23,14 @@ namespace ts.SmartSelectionRange {
// of things that should be considered independently.
// 3. A VariableStatement’s children are just a VaraiableDeclarationList and a semicolon.
// 4. A lone VariableDeclaration in a VaraibleDeclaration feels redundant with the VariableStatement.
//
// Dive in without pushing a selection range.
if (isBlock(node)
|| isTemplateSpan(node) || isTemplateHead(node) || isTemplateTail(node)
|| prevNode && isTemplateHead(prevNode)
|| isVariableDeclarationList(node) && isVariableStatement(parentNode)
|| isSyntaxList(node) && isVariableDeclarationList(parentNode)
|| isVariableDeclaration(node) && isSyntaxList(parentNode) && children.length === 1) {
|| isVariableDeclaration(node) && isSyntaxList(parentNode) && children.length === 1
|| isJSDocTypeExpression(node) || isJSDocSignature(node) || isJSDocTypeLiteral(node)) {
parentNode = node;
break;
}
@@ -44,16 +44,15 @@ namespace ts.SmartSelectionRange {
// Blocks with braces, brackets, parens, or JSX tags on separate lines should be
// selected from open to close, including whitespace but not including the braces/etc. themselves.
const isBetweenMultiLineBookends = isSyntaxList(node)
&& isListOpener(prevNode)
&& isListCloser(nextNode)
const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode)
&& !positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile);
const jsDocCommentStart = hasJSDocNodes(node) && node.jsDoc![0].getStart();
const start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart();
const end = isBetweenMultiLineBookends ? nextNode.getStart() : node.getEnd();
if (isNumber(jsDocCommentStart)) {
pushSelectionRange(jsDocCommentStart, end);
const end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node);
if (hasJSDocNodes(node) && node.jsDoc?.length) {
pushSelectionRange(first(node.jsDoc).getStart(), end);
}
pushSelectionRange(start, end);
// String literals should have a stop both inside and outside their quotes.
@@ -270,4 +269,17 @@ namespace ts.SmartSelectionRange {
|| kind === SyntaxKind.CloseParenToken
|| kind === SyntaxKind.JsxClosingElement;
}
function getEndPos(sourceFile: SourceFile, node: Node): number {
switch (node.kind) {
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocPropertyTag:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocThisTag:
return sourceFile.getLineEndOfPosition(node.getStart());
default:
return node.getEnd();
}
}
}
@@ -0,0 +1,30 @@
/**
* @returns {Array<{ value: /**/string }>}
*/
function foo() { return [] }
string
value: string
{ value: string }
Array<{ value: string }>
@returns {Array<{ value: string }>}
/**
* @returns {Array<{ value: string }>}
*/
/**
* @returns {Array<{ value: string }>}
*/
function foo() { return [] }
@@ -0,0 +1,29 @@
/**
* @template T
* @extends {/**/Set<T>}
*/
class A extends B {
}
Set
Set<T>
@extends {Set<T>}
/**
* @template T
* @extends {Set<T>}
*/
/**
* @template T
* @extends {Set<T>}
*/
class A extends B {
}
@@ -0,0 +1,21 @@
/**
* @type {/**/string}
*/
const foo;
string
@type {string}
/**
* @type {string}
*/
/**
* @type {string}
*/
const foo;
@@ -0,0 +1,21 @@
/**
* @param {/**/string} x
*/
function foo(x) {}
string
@param {string} x
/**
* @param {string} x
*/
/**
* @param {string} x
*/
function foo(x) {}
@@ -0,0 +1,34 @@
/**
* @typedef {object} Foo
* @property {string} a
* @property {number} b
* @property {/**/number} c
*/
/** @type {Foo} */
const foo;
number
@property {number} c
/**
* @typedef {object} Foo
* @property {string} a
* @property {number} b
* @property {number} c
*/
/**
* @typedef {object} Foo
* @property {string} a
* @property {number} b
* @property {number} c
*/
/** @type {Foo} */
const foo;
@@ -0,0 +1,34 @@
/**
* @callback Foo
* @param {string} data
* @param {/**/number} [index] - comment
* @return {boolean}
*/
/** @type {Foo} */
const foo = s => !(s.length % 2);
number
@param {number} [index] - comment
/**
* @callback Foo
* @param {string} data
* @param {number} [index] - comment
* @return {boolean}
*/
/**
* @callback Foo
* @param {string} data
* @param {number} [index] - comment
* @return {boolean}
*/
/** @type {Foo} */
const foo = s => !(s.length % 2);
@@ -0,0 +1,31 @@
/**
* @template T
* @param {/**/T} x
* @return {T}
*/
function foo(x) {
return x;
}
T
@param {T} x
/**
* @template T
* @param {T} x
* @return {T}
*/
/**
* @template T
* @param {T} x
* @return {T}
*/
function foo(x) {
return x;
}
@@ -0,0 +1,26 @@
/**
* @constructor
* @param {/**/number} data
*/
function Foo(data) {
}
number
@param {number} data
/**
* @constructor
* @param {number} data
*/
/**
* @constructor
* @param {number} data
*/
function Foo(data) {
}
@@ -0,0 +1,55 @@
/**
* @this {/**/Foo}
* @param {*} e
*/
function callback(e) {
}
Foo
@this {Foo}
/**
* @this {Foo}
* @param {*} e
*/
/**
* @this {Foo}
* @param {*} e
*/
function callback(e) {
}
================================================================================
/**
* @this {Foo}
* @param {/**/*} e
*/
function callback(e) {
}
*
@param {*} e
/**
* @this {Foo}
* @param {*} e
*/
/**
* @this {Foo}
* @param {*} e
*/
function callback(e) {
}
@@ -0,0 +1,21 @@
/** @enum {/**/number} */
const Foo = {
x: 0,
y: 1,
};
number
@enum {number}
/** @enum {number} */
/** @enum {number} */
const Foo = {
x: 0,
y: 1,
};
@@ -0,0 +1,8 @@
/// <reference path="fourslash.ts" />
/////**
//// * @returns {Array<{ value: /**/string }>}
//// */
////function foo() { return [] }
verify.baselineSmartSelection();
@@ -0,0 +1,11 @@
/// <reference path="fourslash.ts" />
/////**
//// * @template T
//// * @extends {/**/Set<T>}
//// */
////class A extends B {
////}
verify.baselineSmartSelection();
@@ -0,0 +1,8 @@
/// <reference path="fourslash.ts" />
/////**
//// * @type {/**/string}
//// */
////const foo;
verify.baselineSmartSelection();
@@ -0,0 +1,8 @@
/// <reference path="fourslash.ts" />
/////**
//// * @param {/**/string} x
//// */
////function foo(x) {}
verify.baselineSmartSelection();
@@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
/////**
//// * @typedef {object} Foo
//// * @property {string} a
//// * @property {number} b
//// * @property {/**/number} c
//// */
////
/////** @type {Foo} */
////const foo;
verify.baselineSmartSelection();
@@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
/////**
//// * @callback Foo
//// * @param {string} data
//// * @param {/**/number} [index] - comment
//// * @return {boolean}
//// */
////
/////** @type {Foo} */
////const foo = s => !(s.length % 2);
verify.baselineSmartSelection();
@@ -0,0 +1,12 @@
/// <reference path="fourslash.ts" />
/////**
//// * @template T
//// * @param {/**/T} x
//// * @return {T}
//// */
////function foo(x) {
//// return x;
////}
verify.baselineSmartSelection();
@@ -0,0 +1,10 @@
/// <reference path="fourslash.ts" />
/////**
//// * @constructor
//// * @param {/**/number} data
//// */
////function Foo(data) {
////}
verify.baselineSmartSelection();
@@ -0,0 +1,10 @@
/// <reference path="fourslash.ts" />
/////**
//// * @this {/*1*/Foo}
//// * @param {/*2*/*} e
//// */
////function callback(e) {
////}
verify.baselineSmartSelection();
@@ -0,0 +1,9 @@
/// <reference path="fourslash.ts" />
/////** @enum {/**/number} */
////const Foo = {
//// x: 0,
//// y: 1,
////};
verify.baselineSmartSelection();