Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1550,7 +1550,7 @@ export function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportD
case SyntaxKind.ExportSpecifier:
return (node as ExportSpecifier).isTypeOnly || (node as ExportSpecifier).parent.parent.isTypeOnly;
case SyntaxKind.ExportDeclaration:
return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier && !(node as ExportDeclaration).exportClause;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those extra requirements were quite odd here (and got in a way of the tests I was adding for type keyword inclusion/exclusion). An export declaration should be treated as type-only regardless of the existence of other fields on that export declaration AST node. The introduced change also matches the import-oriented counterpart of the containing function (isTypeOnlyImportDeclaration) where there are no extra conditions in the SyntaxKind.ImportSpecifier case.

return (node as ExportDeclaration).isTypeOnly;
case SyntaxKind.NamespaceExport:
return (node as NamespaceExport).parent.isTypeOnly;
}
Expand Down
6 changes: 4 additions & 2 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ import {
isImportDeclaration,
isImportEqualsDeclaration,
isImportKeyword,
isImportOrExportSpecifier,
isImportSpecifier,
isInComment,
isIndexSignatureDeclaration,
Expand Down Expand Up @@ -4651,7 +4652,7 @@ function getCompletionData(
if (!namedImportsOrExports) return GlobalsSearch.Continue;

// We can at least offer `type` at `import { |`
if (!isTypeKeywordTokenOrIdentifier(contextToken)) {
if (!isTypeKeywordTokenOrIdentifier(contextToken) && !isTypeOnlyImportOrExportDeclaration(contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken ? contextToken.parent.parent : contextToken.parent)) {
keywordFilters = KeywordCompletionFilters.TypeKeyword;
}

Expand Down Expand Up @@ -5007,7 +5008,8 @@ function getCompletionData(

case SyntaxKind.TypeKeyword:
// import { type foo| }
return containingNodeKind !== SyntaxKind.ImportSpecifier;
// export { type foo| }
return !isImportOrExportSpecifier(parent);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only change needed to accomplish the goal of this PR. I threw in the rest of the changes to fix some redundant type keyword completions (all of that is reflected by the tests I added)


case SyntaxKind.AsteriskToken:
return isFunctionLike(contextToken.parent) && !isMethodDeclaration(contextToken.parent);
Expand Down
26 changes: 26 additions & 0 deletions tests/cases/fourslash/completionListInExportClause04.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference path='fourslash.ts'/>

// @Filename: m1.ts
//// export var foo: number = 1;
//// export var jkl: number = 2;
//// export type MyType = string;

// @Filename: m2.ts
//// export { /*1*/ } from "./m1"
//// export type { /*2*/ } from "./m1"
//// export { type /*3*/ } from "./m1"
//// export { foo as foo1, /*4*/ } from "./m1"
//// export type { foo as foo2, /*5*/ } from "./m1"
////
//// export { M/*6*/ } from "./m1"
//// export type { M/*7*/ } from "./m1"
//// export { type M/*8*/ } from "./m1"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing this is the main goal of this PR. At the moment, on the main branch this errors with:

Error: At marker '8': No completions at position '232'


const type = { name: "type", sortText: completion.SortText.GlobalsOrKeywords };

verify.completions(
{ marker: ["1", "6"], exact: ["foo", "jkl", "MyType", type] },
{ marker: ["2", "3", "7", "8"], exact: ["foo", "jkl", "MyType"] },
{ marker: "4", exact: ["jkl", "MyType", type] },
{ marker: "5", exact: ["jkl", "MyType"] },
);
26 changes: 26 additions & 0 deletions tests/cases/fourslash/completionListInImportClause07.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference path='fourslash.ts'/>

// @Filename: m1.ts
//// export var foo: number = 1;
//// export var jkl: number = 2;
//// export type MyType = string;

// @Filename: m2.ts
//// import { /*1*/ } from "./m1"
//// import type { /*2*/ } from "./m1"
//// import { type /*3*/ } from "./m1"
//// import { foo as foo1, /*4*/ } from "./m1"
//// import type { foo as foo2, /*5*/ } from "./m1"
////
//// import { M/*6*/ } from "./m1"
//// import type { M/*7*/ } from "./m1"
//// import { type M/*8*/ } from "./m1"

const type = { name: "type", sortText: completion.SortText.GlobalsOrKeywords };

verify.completions(
{ marker: ["1", "6"], exact: ["foo", "jkl", "MyType", type] },
{ marker: ["2", "3", "7", "8"], exact: ["foo", "jkl", "MyType"] },
{ marker: "4", exact: ["jkl", "MyType", type] },
{ marker: "5", exact: ["jkl", "MyType"] },
);