From f04672842b4e8531d96dddf8d7d741402c1ea569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 12 Aug 2024 23:36:03 +0200 Subject: [PATCH] Fixed completion crashes related to `JSDocImportTag` (#59527) --- src/compiler/binder.ts | 5 ++- ...larationAttributesEmptyModuleSpecifier1.ts | 17 ++++++++++ ...larationAttributesErrorModuleSpecifier1.ts | 17 ++++++++++ ...mportTagAttributesEmptyModuleSpecifier1.ts | 19 ++++++++++++ ...mportTagAttributesErrorModuleSpecifier1.ts | 19 ++++++++++++ ...ionsJSDocImportTagEmptyModuleSpecifier1.ts | 18 +++++++++++ .../fourslash/completionsJSDocNoCrash1.ts | 31 +++++++++++++++++++ .../fourslash/completionsJSDocNoCrash2.ts | 29 +++++++++++++++++ 8 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/completionsImportDeclarationAttributesEmptyModuleSpecifier1.ts create mode 100644 tests/cases/fourslash/completionsImportDeclarationAttributesErrorModuleSpecifier1.ts create mode 100644 tests/cases/fourslash/completionsJSDocImportTagAttributesEmptyModuleSpecifier1.ts create mode 100644 tests/cases/fourslash/completionsJSDocImportTagAttributesErrorModuleSpecifier1.ts create mode 100644 tests/cases/fourslash/completionsJSDocImportTagEmptyModuleSpecifier1.ts create mode 100644 tests/cases/fourslash/completionsJSDocNoCrash1.ts create mode 100644 tests/cases/fourslash/completionsJSDocNoCrash2.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5c94dde5cc5..96c6e08f0f5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1191,10 +1191,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.JSDocEnumTag: bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); break; - // In source files and blocks, bind functions first to match hoisting that occurs at runtime case SyntaxKind.JSDocImportTag: bindJSDocImportTag(node as JSDocImportTag); break; + // In source files and blocks, bind functions first to match hoisting that occurs at runtime case SyntaxKind.SourceFile: { bindEachFunctionsFirst((node as SourceFile).statements); bind((node as SourceFile).endOfFileToken); @@ -2105,7 +2105,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function bindJSDocImportTag(node: JSDocImportTag) { + // don't bind the importClause yet; that's delayed until bindJSDocImports bind(node.tagName); + bind(node.moduleSpecifier); + bind(node.attributes); if (typeof node.comment !== "string") { bindEach(node.comment); diff --git a/tests/cases/fourslash/completionsImportDeclarationAttributesEmptyModuleSpecifier1.ts b/tests/cases/fourslash/completionsImportDeclarationAttributesEmptyModuleSpecifier1.ts new file mode 100644 index 00000000000..f083815dfcb --- /dev/null +++ b/tests/cases/fourslash/completionsImportDeclarationAttributesEmptyModuleSpecifier1.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true + +// @filename: global.d.ts +//// interface ImportAttributes { +//// type: "json"; +//// } + +// @filename: index.ts +//// import * as ns from "" with { type: "/**/" }; + +verify.completions({ + marker: "", + exact: ["json"], + isNewIdentifierLocation: false, +}); diff --git a/tests/cases/fourslash/completionsImportDeclarationAttributesErrorModuleSpecifier1.ts b/tests/cases/fourslash/completionsImportDeclarationAttributesErrorModuleSpecifier1.ts new file mode 100644 index 00000000000..bbad49da515 --- /dev/null +++ b/tests/cases/fourslash/completionsImportDeclarationAttributesErrorModuleSpecifier1.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true + +// @filename: global.d.ts +//// interface ImportAttributes { +//// type: "json"; +//// } + +// @filename: index.ts +//// import * as ns from () with { type: "/**/" }; + +verify.completions({ + marker: "", + exact: ["json"], + isNewIdentifierLocation: false, +}); diff --git a/tests/cases/fourslash/completionsJSDocImportTagAttributesEmptyModuleSpecifier1.ts b/tests/cases/fourslash/completionsJSDocImportTagAttributesEmptyModuleSpecifier1.ts new file mode 100644 index 00000000000..ad23ca3b933 --- /dev/null +++ b/tests/cases/fourslash/completionsJSDocImportTagAttributesEmptyModuleSpecifier1.ts @@ -0,0 +1,19 @@ +/// + +// @strict: true +// @checkJs: true +// @allowJs: true + +// @filename: global.d.ts +//// interface ImportAttributes { +//// type: "json"; +//// } + +// @filename: index.js +//// /** @import * as ns from "" with { type: "/**/" } */ + +verify.completions({ + marker: "", + exact: ["json"], + isNewIdentifierLocation: false, +}); diff --git a/tests/cases/fourslash/completionsJSDocImportTagAttributesErrorModuleSpecifier1.ts b/tests/cases/fourslash/completionsJSDocImportTagAttributesErrorModuleSpecifier1.ts new file mode 100644 index 00000000000..56825e73e3f --- /dev/null +++ b/tests/cases/fourslash/completionsJSDocImportTagAttributesErrorModuleSpecifier1.ts @@ -0,0 +1,19 @@ +/// + +// @strict: true +// @checkJs: true +// @allowJs: true + +// @filename: global.d.ts +//// interface ImportAttributes { +//// type: "json"; +//// } + +// @filename: index.js +//// /** @import * as ns from () with { type: "/**/" } */ + +verify.completions({ + marker: "", + exact: ["json"], + isNewIdentifierLocation: false, +}); diff --git a/tests/cases/fourslash/completionsJSDocImportTagEmptyModuleSpecifier1.ts b/tests/cases/fourslash/completionsJSDocImportTagEmptyModuleSpecifier1.ts new file mode 100644 index 00000000000..ccbe067406e --- /dev/null +++ b/tests/cases/fourslash/completionsJSDocImportTagEmptyModuleSpecifier1.ts @@ -0,0 +1,18 @@ +/// + +// @strict: true +// @checkJs: true +// @allowJs: true +// @moduleResolution: nodenext + +// @filename: node_modules/pkg/index.d.ts +//// export type MyUnion = string | number; + +// @filename: index.js +//// /** @import { MyUnion } from "/**/" */ + +verify.completions({ + marker: "", + exact: ["pkg"], + isNewIdentifierLocation: true, +}); diff --git a/tests/cases/fourslash/completionsJSDocNoCrash1.ts b/tests/cases/fourslash/completionsJSDocNoCrash1.ts new file mode 100644 index 00000000000..a5aa659a9e0 --- /dev/null +++ b/tests/cases/fourslash/completionsJSDocNoCrash1.ts @@ -0,0 +1,31 @@ +/// + +// @strict: true +// @checkJs: true +// @allowJs: true + +// @filename: index.js +//// /** +//// * @example +//// +//// @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css); +//// +//// +//// +//// .animate-show.ng-hide-add.ng-hide-add-active, +//// .animate-show.ng-hide-remove.ng-hide-remove-active { +//// transition:all linear 0./**/5s; +//// } +//// +//// +//// */ +//// var ngShowDirective = ['$animate', function($animate) {}]; + +verify.completions({ + marker: "", + includes: ["url"], + isNewIdentifierLocation: true, + preferences: { + includeCompletionsWithInsertText: true + } +}); diff --git a/tests/cases/fourslash/completionsJSDocNoCrash2.ts b/tests/cases/fourslash/completionsJSDocNoCrash2.ts new file mode 100644 index 00000000000..e37d4452245 --- /dev/null +++ b/tests/cases/fourslash/completionsJSDocNoCrash2.ts @@ -0,0 +1,29 @@ +/// + +// @strict: true + +// @filename: index.ts +//// /** +//// * @example +//// +//// @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css); +//// +//// +//// +//// .animate-show.ng-hide-add.ng-hide-add-active, +//// .animate-show.ng-hide-remove.ng-hide-remove-active { +//// transition:all linear 0./**/5s; +//// } +//// +//// +//// */ +//// var ngShowDirective = ['$animate', function($animate) {}]; + +verify.completions({ + marker: "", + exact: completion.globalTypes, + isNewIdentifierLocation: false, + preferences: { + includeCompletionsWithInsertText: true + } +});