@@ -831,7 +831,8 @@ namespace ts.Completions {
831831 // * |c|
832832 // */
833833 const lineStart = getLineStartPositionForPosition ( position , sourceFile ) ;
834- const m = / ^ (?: [ * \s ] + | \s * \/ \* \* \s + ) ( @ ) ? $ / . exec (
834+ // jsdoc tag will be listed if there is more than one whitespace after "*"
835+ const m = / ^ (?: \s * (?: [ * \s ] + (? = \s ) ) ? \s + | \s * \/ \* \* \s + ) ( @ ) ? $ / . exec (
835836 sourceFile . text . substring ( lineStart , position )
836837 ) ;
837838 if ( m ) {
@@ -1271,6 +1272,7 @@ namespace ts.Completions {
12711272 function tryGetGlobalSymbols ( ) : boolean {
12721273 const result : GlobalsSearch = tryGetObjectLikeCompletionSymbols ( )
12731274 || tryGetImportOrExportClauseCompletionSymbols ( )
1275+ || tryGetLocalNamedExportCompletionSymbols ( )
12741276 || tryGetConstructorCompletion ( )
12751277 || tryGetClassLikeCompletionSymbols ( )
12761278 || tryGetJsxCompletionSymbols ( )
@@ -1881,19 +1883,17 @@ namespace ts.Completions {
18811883 * export { | };
18821884 *
18831885 * Relevant symbols are stored in the captured 'symbols' variable.
1884- *
1885- * @returns true if 'symbols' was successfully populated; false otherwise.
18861886 */
18871887 function tryGetImportOrExportClauseCompletionSymbols ( ) : GlobalsSearch {
18881888 // `import { |` or `import { a as 0, | }`
18891889 const namedImportsOrExports = contextToken && ( contextToken . kind === SyntaxKind . OpenBraceToken || contextToken . kind === SyntaxKind . CommaToken )
18901890 ? tryCast ( contextToken . parent , isNamedImportsOrExports ) : undefined ;
18911891 if ( ! namedImportsOrExports ) return GlobalsSearch . Continue ;
18921892
1893- // cursor is in an import clause
1894- // try to show exported member for imported module
1893+ // try to show exported member for imported/re-exported module
18951894 const { moduleSpecifier } = namedImportsOrExports . kind === SyntaxKind . NamedImports ? namedImportsOrExports . parent . parent : namedImportsOrExports . parent ;
1896- const moduleSpecifierSymbol = typeChecker . getSymbolAtLocation ( moduleSpecifier ! ) ; // TODO: GH#18217
1895+ if ( ! moduleSpecifier ) return namedImportsOrExports . kind === SyntaxKind . NamedImports ? GlobalsSearch . Fail : GlobalsSearch . Continue ;
1896+ const moduleSpecifierSymbol = typeChecker . getSymbolAtLocation ( moduleSpecifier ) ; // TODO: GH#18217
18971897 if ( ! moduleSpecifierSymbol ) return GlobalsSearch . Fail ;
18981898
18991899 completionKind = CompletionKind . MemberLike ;
@@ -1904,6 +1904,36 @@ namespace ts.Completions {
19041904 return GlobalsSearch . Success ;
19051905 }
19061906
1907+ /**
1908+ * Adds local declarations for completions in named exports:
1909+ *
1910+ * export { | };
1911+ *
1912+ * Does not check for the absence of a module specifier (`export {} from "./other"`)
1913+ * because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
1914+ * preventing this function from running.
1915+ */
1916+ function tryGetLocalNamedExportCompletionSymbols ( ) : GlobalsSearch {
1917+ const namedExports = contextToken && ( contextToken . kind === SyntaxKind . OpenBraceToken || contextToken . kind === SyntaxKind . CommaToken )
1918+ ? tryCast ( contextToken . parent , isNamedExports )
1919+ : undefined ;
1920+
1921+ if ( ! namedExports ) {
1922+ return GlobalsSearch . Continue ;
1923+ }
1924+
1925+ const localsContainer = findAncestor ( namedExports , or ( isSourceFile , isModuleDeclaration ) ) ! ;
1926+ completionKind = CompletionKind . None ;
1927+ isNewIdentifierLocation = false ;
1928+ localsContainer . locals ?. forEach ( ( symbol , name ) => {
1929+ symbols . push ( symbol ) ;
1930+ if ( localsContainer . symbol ?. exports ?. has ( name ) ) {
1931+ symbolToSortTextMap [ getSymbolId ( symbol ) ] = SortText . OptionalMember ;
1932+ }
1933+ } ) ;
1934+ return GlobalsSearch . Success ;
1935+ }
1936+
19071937 /**
19081938 * Aggregates relevant symbols for completion in class declaration
19091939 * Relevant symbols are stored in the captured 'symbols' variable.
@@ -2299,7 +2329,7 @@ namespace ts.Completions {
22992329 }
23002330 }
23012331
2302- // Set SortText to OptionalMember if it is an optinoal member
2332+ // Set SortText to OptionalMember if it is an optional member
23032333 function setSortTextToOptionalMember ( ) {
23042334 symbols . forEach ( m => {
23052335 if ( m . flags & SymbolFlags . Optional ) {
0 commit comments