Skip to content

Commit afcced6

Browse files
author
Andy
authored
Simplify tryGetImportOrExportClauseCompletionSymbols (#22961)
* Simplify tryGetImportOrExportClauseCompletionSymbols * Handle undefined key in arrayToSet
1 parent d2dc2e6 commit afcced6

File tree

3 files changed

+22
-70
lines changed

3 files changed

+22
-70
lines changed

src/compiler/core.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,12 +1314,13 @@ namespace ts {
13141314
* the same key with the given 'makeKey' function, then the element with the higher
13151315
* index in the array will be the one associated with the produced key.
13161316
*/
1317-
export function arrayToMap<T>(array: ReadonlyArray<T>, makeKey: (value: T) => string): Map<T>;
1318-
export function arrayToMap<T, U>(array: ReadonlyArray<T>, makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
1319-
export function arrayToMap<T, U>(array: ReadonlyArray<T>, makeKey: (value: T) => string, makeValue: (value: T) => T | U = identity): Map<T | U> {
1317+
export function arrayToMap<T>(array: ReadonlyArray<T>, makeKey: (value: T) => string | undefined): Map<T>;
1318+
export function arrayToMap<T, U>(array: ReadonlyArray<T>, makeKey: (value: T) => string | undefined, makeValue: (value: T) => U): Map<U>;
1319+
export function arrayToMap<T, U>(array: ReadonlyArray<T>, makeKey: (value: T) => string | undefined, makeValue: (value: T) => T | U = identity): Map<T | U> {
13201320
const result = createMap<T | U>();
13211321
for (const value of array) {
1322-
result.set(makeKey(value), makeValue(value));
1322+
const key = makeKey(value);
1323+
if (key !== undefined) result.set(key, makeValue(value));
13231324
}
13241325
return result;
13251326
}
@@ -1340,8 +1341,9 @@ namespace ts {
13401341
* @param array the array of input elements.
13411342
*/
13421343
export function arrayToSet(array: ReadonlyArray<string>): Map<true>;
1343-
export function arrayToSet<T>(array: ReadonlyArray<T>, makeKey: (value: T) => string): Map<true>;
1344-
export function arrayToSet(array: ReadonlyArray<any>, makeKey?: (value: any) => string): Map<true> {
1344+
export function arrayToSet<T>(array: ReadonlyArray<T>, makeKey: (value: T) => string | undefined): Map<true>;
1345+
export function arrayToSet<T>(array: ReadonlyArray<T>, makeKey: (value: T) => __String | undefined): UnderscoreEscapedMap<true>;
1346+
export function arrayToSet(array: ReadonlyArray<any>, makeKey?: (value: any) => string | __String | undefined): Map<true> | UnderscoreEscapedMap<true> {
13451347
return arrayToMap<any, true>(array, makeKey || (s => s), () => true);
13461348
}
13471349

src/compiler/utilities.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6325,4 +6325,9 @@ namespace ts {
63256325
export function isStringLiteralLike(node: Node): node is StringLiteralLike {
63266326
return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
63276327
}
6328+
6329+
/** @internal */
6330+
export function isNamedImportsOrExports(node: Node): node is NamedImportsOrExports {
6331+
return node.kind === SyntaxKind.NamedImports || node.kind === SyntaxKind.NamedExports;
6332+
}
63286333
}

src/services/completions.ts

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,32 +1555,22 @@ namespace ts.Completions {
15551555
* @returns true if 'symbols' was successfully populated; false otherwise.
15561556
*/
15571557
function tryGetImportOrExportClauseCompletionSymbols(): GlobalsSearch {
1558-
const namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken);
1559-
if (!namedImportsOrExports) return undefined;
1558+
// `import { |` or `import { a as 0, | }`
1559+
const namedImportsOrExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
1560+
? tryCast(contextToken.parent, isNamedImportsOrExports) : undefined;
1561+
if (!namedImportsOrExports) return GlobalsSearch.Continue;
15601562

15611563
// cursor is in an import clause
15621564
// try to show exported member for imported module
1563-
const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ?
1564-
SyntaxKind.ImportDeclaration :
1565-
SyntaxKind.ExportDeclaration;
1566-
const importOrExportDeclaration = <ImportDeclaration | ExportDeclaration>getAncestor(namedImportsOrExports, declarationKind);
1567-
const moduleSpecifier = importOrExportDeclaration.moduleSpecifier;
1568-
1569-
if (!moduleSpecifier) {
1570-
return GlobalsSearch.Fail;
1571-
}
1565+
const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent;
1566+
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
1567+
if (!moduleSpecifierSymbol) return GlobalsSearch.Fail;
15721568

15731569
completionKind = CompletionKind.MemberLike;
15741570
isNewIdentifierLocation = false;
1575-
1576-
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
1577-
if (!moduleSpecifierSymbol) {
1578-
symbols = emptyArray;
1579-
return GlobalsSearch.Fail;
1580-
}
1581-
15821571
const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
1583-
symbols = filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements);
1572+
const existing = arrayToSet<ImportOrExportSpecifier>(namedImportsOrExports.elements, n => isCurrentlyEditingNode(n) ? undefined : (n.propertyName || n.name).escapedText);
1573+
symbols = exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.get(e.escapedName));
15841574
return GlobalsSearch.Success;
15851575
}
15861576

@@ -1648,26 +1638,6 @@ namespace ts.Completions {
16481638
return undefined;
16491639
}
16501640

1651-
/**
1652-
* Returns the containing list of named imports or exports of a context token,
1653-
* on the condition that one exists and that the context implies completion should be given.
1654-
*/
1655-
function tryGetNamedImportsOrExportsForCompletion(contextToken: Node): NamedImportsOrExports {
1656-
if (contextToken) {
1657-
switch (contextToken.kind) {
1658-
case SyntaxKind.OpenBraceToken: // import { |
1659-
case SyntaxKind.CommaToken: // import { a as 0, |
1660-
switch (contextToken.parent.kind) {
1661-
case SyntaxKind.NamedImports:
1662-
case SyntaxKind.NamedExports:
1663-
return <NamedImportsOrExports>contextToken.parent;
1664-
}
1665-
}
1666-
}
1667-
1668-
return undefined;
1669-
}
1670-
16711641
function isConstructorParameterCompletion(node: Node): boolean {
16721642
return !!node.parent && isParameter(node.parent) && isConstructorDeclaration(node.parent.parent)
16731643
&& (isParameterPropertyModifier(node.kind) || isDeclarationName(node));
@@ -1911,31 +1881,6 @@ namespace ts.Completions {
19111881
return false;
19121882
}
19131883

1914-
/**
1915-
* Filters out completion suggestions for named imports or exports.
1916-
*
1917-
* @param exportsOfModule The list of symbols which a module exposes.
1918-
* @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause.
1919-
*
1920-
* @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports
1921-
* do not occur at the current position and have not otherwise been typed.
1922-
*/
1923-
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ReadonlyArray<ImportOrExportSpecifier>): Symbol[] {
1924-
const existingImportsOrExports = createUnderscoreEscapedMap<boolean>();
1925-
1926-
for (const element of namedImportsOrExports) {
1927-
// If this is the current item we are editing right now, do not filter it out
1928-
if (isCurrentlyEditingNode(element)) {
1929-
continue;
1930-
}
1931-
1932-
const name = element.propertyName || element.name;
1933-
existingImportsOrExports.set(name.escapedText, true);
1934-
}
1935-
1936-
return exportsOfModule.filter(e => e.escapedName !== InternalSymbolName.Default && !existingImportsOrExports.get(e.escapedName));
1937-
}
1938-
19391884
/**
19401885
* Filters out completion suggestions for named imports or exports.
19411886
*

0 commit comments

Comments
 (0)