@@ -1271,6 +1271,7 @@ namespace ts.Completions {
12711271 function tryGetGlobalSymbols ( ) : boolean {
12721272 const result : GlobalsSearch = tryGetObjectLikeCompletionSymbols ( )
12731273 || tryGetImportOrExportClauseCompletionSymbols ( )
1274+ || tryGetLocalNamedExportCompletionSymbols ( )
12741275 || tryGetConstructorCompletion ( )
12751276 || tryGetClassLikeCompletionSymbols ( )
12761277 || tryGetJsxCompletionSymbols ( )
@@ -1881,19 +1882,17 @@ namespace ts.Completions {
18811882 * export { | };
18821883 *
18831884 * Relevant symbols are stored in the captured 'symbols' variable.
1884- *
1885- * @returns true if 'symbols' was successfully populated; false otherwise.
18861885 */
18871886 function tryGetImportOrExportClauseCompletionSymbols ( ) : GlobalsSearch {
18881887 // `import { |` or `import { a as 0, | }`
18891888 const namedImportsOrExports = contextToken && ( contextToken . kind === SyntaxKind . OpenBraceToken || contextToken . kind === SyntaxKind . CommaToken )
18901889 ? tryCast ( contextToken . parent , isNamedImportsOrExports ) : undefined ;
18911890 if ( ! namedImportsOrExports ) return GlobalsSearch . Continue ;
18921891
1893- // cursor is in an import clause
1894- // try to show exported member for imported module
1892+ // try to show exported member for imported/re-exported module
18951893 const { moduleSpecifier } = namedImportsOrExports . kind === SyntaxKind . NamedImports ? namedImportsOrExports . parent . parent : namedImportsOrExports . parent ;
1896- const moduleSpecifierSymbol = typeChecker . getSymbolAtLocation ( moduleSpecifier ! ) ; // TODO: GH#18217
1894+ if ( ! moduleSpecifier ) return namedImportsOrExports . kind === SyntaxKind . NamedImports ? GlobalsSearch . Fail : GlobalsSearch . Continue ;
1895+ const moduleSpecifierSymbol = typeChecker . getSymbolAtLocation ( moduleSpecifier ) ; // TODO: GH#18217
18971896 if ( ! moduleSpecifierSymbol ) return GlobalsSearch . Fail ;
18981897
18991898 completionKind = CompletionKind . MemberLike ;
@@ -1904,6 +1903,36 @@ namespace ts.Completions {
19041903 return GlobalsSearch . Success ;
19051904 }
19061905
1906+ /**
1907+ * Adds local declarations for completions in named exports:
1908+ *
1909+ * export { | };
1910+ *
1911+ * Does not check for the absence of a module specifier (`export {} from "./other"`)
1912+ * because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
1913+ * preventing this function from running.
1914+ */
1915+ function tryGetLocalNamedExportCompletionSymbols ( ) : GlobalsSearch {
1916+ const namedExports = contextToken && ( contextToken . kind === SyntaxKind . OpenBraceToken || contextToken . kind === SyntaxKind . CommaToken )
1917+ ? tryCast ( contextToken . parent , isNamedExports )
1918+ : undefined ;
1919+
1920+ if ( ! namedExports ) {
1921+ return GlobalsSearch . Continue ;
1922+ }
1923+
1924+ const localsContainer = findAncestor ( namedExports , or ( isSourceFile , isModuleDeclaration ) ) ! ;
1925+ completionKind = CompletionKind . None ;
1926+ isNewIdentifierLocation = false ;
1927+ localsContainer . locals ?. forEach ( ( symbol , name ) => {
1928+ symbols . push ( symbol ) ;
1929+ if ( localsContainer . symbol ?. exports ?. has ( name ) ) {
1930+ symbolToSortTextMap [ getSymbolId ( symbol ) ] = SortText . OptionalMember ;
1931+ }
1932+ } ) ;
1933+ return GlobalsSearch . Success ;
1934+ }
1935+
19071936 /**
19081937 * Aggregates relevant symbols for completion in class declaration
19091938 * Relevant symbols are stored in the captured 'symbols' variable.
@@ -2299,7 +2328,7 @@ namespace ts.Completions {
22992328 }
23002329 }
23012330
2302- // Set SortText to OptionalMember if it is an optinoal member
2331+ // Set SortText to OptionalMember if it is an optional member
23032332 function setSortTextToOptionalMember ( ) {
23042333 symbols . forEach ( m => {
23052334 if ( m . flags & SymbolFlags . Optional ) {
0 commit comments