From 0a20ad3154f4d1a7a3da37f9a9c51d2a4cabb5db Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Wed, 31 Jan 2024 00:56:58 +0200 Subject: [PATCH] jsdoc import type find-all-refs/rename --- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 3 +- src/services/importTracker.ts | 6 +- ...ndAllRefsJsDocImportTypeTag.baseline.jsonc | 105 ++++++++++++++++++ .../renameJsDocImportTypeTag.baseline.jsonc | 10 ++ .../findAllRefsJsDocImportTypeTag.ts | 19 ++++ .../fourslash/renameJsDocImportTypeTag.ts | 19 ++++ 7 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/findAllRefsJsDocImportTypeTag.baseline.jsonc create mode 100644 tests/baselines/reference/renameJsDocImportTypeTag.baseline.jsonc create mode 100644 tests/cases/fourslash/findAllRefsJsDocImportTypeTag.ts create mode 100644 tests/cases/fourslash/renameJsDocImportTypeTag.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5512e0c7712c7..3f542b5b4d1d9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5586,7 +5586,7 @@ export interface ValidImportTypeNode extends ImportTypeNode { /** @internal */ export type AnyValidImportOrReExport = - | (ImportDeclaration | ExportDeclaration) & { moduleSpecifier: StringLiteral; } + | (ImportDeclaration | ExportDeclaration | JSDocImportTypeTag) & { moduleSpecifier: StringLiteral; } | ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteral; }; } | RequireOrImportCall | ValidImportTypeNode; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ee94ea45d6346..71f88d89f54e7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4022,6 +4022,7 @@ export function tryGetImportFromModuleSpecifier(node: StringLiteralLike): AnyVal switch (node.parent.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: + case SyntaxKind.JSDocImportTypeTag: return node.parent as AnyValidImportOrReExport; case SyntaxKind.ExternalModuleReference: return (node.parent as ExternalModuleReference).parent as AnyValidImportOrReExport; @@ -4070,7 +4071,7 @@ export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqua } /** @internal */ -export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { +export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration | JSDocImportTypeTag): boolean { return node.kind === SyntaxKind.ImportDeclaration && !!node.importClause && !!node.importClause.name; } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index b0e7215625e12..b8dc5758def9f 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -57,6 +57,7 @@ import { isVariableDeclaration, isVariableDeclarationInitializedToBareOrAccessedRequire, isVariableStatement, + JSDocImportTypeTag, ModifierFlags, ModuleBlock, ModuleDeclaration, @@ -138,7 +139,7 @@ interface AmbientModuleDeclaration extends ModuleDeclaration { } type SourceFileLike = SourceFile | AmbientModuleDeclaration; // Identifier for the case of `const x = require("y")`. -type Importer = AnyImportOrReExport | ValidImportTypeNode | Identifier; +type Importer = AnyImportOrReExport | ValidImportTypeNode | Identifier | JSDocImportTypeTag; type ImporterOrCallExpression = Importer | CallExpression; /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */ @@ -215,6 +216,7 @@ function getImportersForExport( break; case SyntaxKind.ImportDeclaration: + case SyntaxKind.JSDocImportTypeTag: directImports.push(direct); const namedBindings = direct.importClause && direct.importClause.namedBindings; if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { @@ -267,7 +269,7 @@ function getImportersForExport( }); } - function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void { + function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration | JSDocImportTypeTag, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void { if (exportKind === ExportKind.ExportEquals) { // This is a direct import, not import-as-namespace. if (!alreadyAddedDirect) directImports.push(importDeclaration); diff --git a/tests/baselines/reference/findAllRefsJsDocImportTypeTag.baseline.jsonc b/tests/baselines/reference/findAllRefsJsDocImportTypeTag.baseline.jsonc new file mode 100644 index 0000000000000..7310f74b390b5 --- /dev/null +++ b/tests/baselines/reference/findAllRefsJsDocImportTypeTag.baseline.jsonc @@ -0,0 +1,105 @@ +// === findAllReferences === +// === /a.js === +// /** +// * <|@importType { [|{| defId: 0, isWriteAccess: true |}A|] } from "./b"; +// |>*/ +// +// /** +// * @param { [|{| defId: 0 |}A|]/*FIND ALL REFS*/ } a +// */ +// function f(a) {} + +// === /b.ts === +// <|export interface [|{| defId: 1, isWriteAccess: true |}A|] { }|> + + // === Definitions === + // === /a.js === + // /** + // * <|@importType { [|{| defId: 0 |}A|] } from "./b"; + // |>*/ + // + // /** + // * @param { A/*FIND ALL REFS*/ } a + // */ + // function f(a) {} + + // === /b.ts === + // <|export interface [|{| defId: 1 |}A|] { }|> + + // === Details === + [ + { + "defId": 0, + "containerKind": "", + "containerName": "", + "kind": "alias", + "name": "(alias) interface A\nimport A", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "alias", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "interface", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "A", + "kind": "aliasName" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": "import", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "A", + "kind": "aliasName" + } + ] + }, + { + "defId": 1, + "containerKind": "", + "containerName": "", + "kind": "interface", + "name": "interface A", + "displayParts": [ + { + "text": "interface", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "A", + "kind": "interfaceName" + } + ] + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/renameJsDocImportTypeTag.baseline.jsonc b/tests/baselines/reference/renameJsDocImportTypeTag.baseline.jsonc new file mode 100644 index 0000000000000..89d16ef43ae38 --- /dev/null +++ b/tests/baselines/reference/renameJsDocImportTypeTag.baseline.jsonc @@ -0,0 +1,10 @@ +// === findRenameLocations === +// === /a.js === +// /** +// * <|@importType { /*START PREFIX*/A as [|ARENAME|] } from "./b"; +// |>*/ +// +// /** +// * @param { [|ARENAME|]/*RENAME*/ } a +// */ +// function f(a) {} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsJsDocImportTypeTag.ts b/tests/cases/fourslash/findAllRefsJsDocImportTypeTag.ts new file mode 100644 index 0000000000000..2918fd59c1caf --- /dev/null +++ b/tests/cases/fourslash/findAllRefsJsDocImportTypeTag.ts @@ -0,0 +1,19 @@ +/// + +// @allowJS: true +// @checkJs: true + +// @Filename: /b.ts +////export interface A { } + +// @Filename: /a.js +/////** +//// * @importType { A } from "./b"; +//// */ +//// +/////** +//// * @param { [|A/**/|] } a +//// */ +////function f(a) {} + +verify.baselineFindAllReferences(""); diff --git a/tests/cases/fourslash/renameJsDocImportTypeTag.ts b/tests/cases/fourslash/renameJsDocImportTypeTag.ts new file mode 100644 index 0000000000000..dbd09f2ae7ff5 --- /dev/null +++ b/tests/cases/fourslash/renameJsDocImportTypeTag.ts @@ -0,0 +1,19 @@ +/// + +// @allowJS: true +// @checkJs: true + +// @Filename: /b.ts +////export interface A { } + +// @Filename: /a.js +/////** +//// * @importType { A } from "./b"; +//// */ +//// +/////** +//// * @param { [|A/**/|] } a +//// */ +////function f(a) {} + +verify.baselineRename("");