@@ -20,7 +20,8 @@ namespace ts.Completions {
2020 None ,
2121 ClassElementKeywords , // Keywords at class keyword
2222 ConstructorParameterKeywords , // Keywords at constructor parameter
23- FunctionLikeBodyKeywords // Keywords at function like body
23+ FunctionLikeBodyKeywords , // Keywords at function like body
24+ TypeKeywords ,
2425 }
2526
2627 export function getCompletionsAtPosition (
@@ -565,7 +566,7 @@ namespace ts.Completions {
565566 }
566567 case "none" : {
567568 // Didn't find a symbol with this name. See if we can find a keyword instead.
568- if ( some ( getKeywordCompletions ( KeywordCompletionFilters . None ) , c => c . name === name ) ) {
569+ if ( allKeywordsCompletions ( ) . some ( c => c . name === name ) ) {
569570 return {
570571 name,
571572 kind : ScriptElementKind . keyword ,
@@ -1163,26 +1164,24 @@ namespace ts.Completions {
11631164 }
11641165
11651166 function filterGlobalCompletion ( symbols : Symbol [ ] ) : void {
1167+ const isTypeCompletion = insideJsDocTagTypeExpression || ! isContextTokenValueLocation ( contextToken ) && ( isPartOfTypeNode ( location ) || isContextTokenTypeLocation ( contextToken ) ) ;
1168+ if ( isTypeCompletion ) keywordFilters = KeywordCompletionFilters . TypeKeywords ;
1169+
11661170 filterMutate ( symbols , symbol => {
11671171 if ( ! isSourceFile ( location ) ) {
11681172 // export = /**/ here we want to get all meanings, so any symbol is ok
11691173 if ( isExportAssignment ( location . parent ) ) {
11701174 return true ;
11711175 }
11721176
1173- // This is an alias, follow what it aliases
1174- if ( symbol && symbol . flags & SymbolFlags . Alias ) {
1175- symbol = typeChecker . getAliasedSymbol ( symbol ) ;
1176- }
1177+ symbol = skipAlias ( symbol , typeChecker ) ;
11771178
11781179 // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
11791180 if ( isInRightSideOfInternalImportEqualsDeclaration ( location ) ) {
11801181 return ! ! ( symbol . flags & SymbolFlags . Namespace ) ;
11811182 }
11821183
1183- if ( insideJsDocTagTypeExpression ||
1184- ( ! isContextTokenValueLocation ( contextToken ) &&
1185- ( isPartOfTypeNode ( location ) || isContextTokenTypeLocation ( contextToken ) ) ) ) {
1184+ if ( isTypeCompletion ) {
11861185 // Its a type, but you can reach it by namespace.type as well
11871186 return symbolCanBeReferencedAtTypeLocation ( symbol ) ;
11881187 }
@@ -1199,7 +1198,7 @@ namespace ts.Completions {
11991198 contextToken . parent . kind === SyntaxKind . TypeQuery ;
12001199 }
12011200
1202- function isContextTokenTypeLocation ( contextToken : Node ) {
1201+ function isContextTokenTypeLocation ( contextToken : Node ) : boolean {
12031202 if ( contextToken ) {
12041203 const parentKind = contextToken . parent . kind ;
12051204 switch ( contextToken . kind ) {
@@ -1217,6 +1216,7 @@ namespace ts.Completions {
12171216 return parentKind === SyntaxKind . AsExpression ;
12181217 }
12191218 }
1219+ return false ;
12201220 }
12211221
12221222 function symbolCanBeReferencedAtTypeLocation ( symbol : Symbol ) : boolean {
@@ -2130,51 +2130,38 @@ namespace ts.Completions {
21302130 }
21312131
21322132 // A cache of completion entries for keywords, these do not change between sessions
2133- const _keywordCompletions : CompletionEntry [ ] [ ] = [ ] ;
2134- function getKeywordCompletions ( keywordFilter : KeywordCompletionFilters ) : CompletionEntry [ ] {
2135- const completions = _keywordCompletions [ keywordFilter ] ;
2136- if ( completions ) {
2137- return completions ;
2133+ const _keywordCompletions : ReadonlyArray < CompletionEntry > [ ] = [ ] ;
2134+ const allKeywordsCompletions : ( ) => ReadonlyArray < CompletionEntry > = ts . memoize ( ( ) => {
2135+ const res : CompletionEntry [ ] = [ ] ;
2136+ for ( let i = SyntaxKind . FirstKeyword ; i <= SyntaxKind . LastKeyword ; i ++ ) {
2137+ res . push ( {
2138+ name : tokenToString ( i ) ,
2139+ kind : ScriptElementKind . keyword ,
2140+ kindModifiers : ScriptElementKindModifier . none ,
2141+ sortText : "0"
2142+ } ) ;
21382143 }
2139- return _keywordCompletions [ keywordFilter ] = generateKeywordCompletions ( keywordFilter ) ;
2140-
2141- type FilterKeywordCompletions = ( entryName : string ) => boolean ;
2142- function generateKeywordCompletions ( keywordFilter : KeywordCompletionFilters ) : CompletionEntry [ ] {
2144+ return res ;
2145+ } ) ;
2146+ function getKeywordCompletions ( keywordFilter : KeywordCompletionFilters ) : ReadonlyArray < CompletionEntry > {
2147+ return _keywordCompletions [ keywordFilter ] || ( _keywordCompletions [ keywordFilter ] = allKeywordsCompletions ( ) . filter ( entry => {
2148+ const kind = stringToToken ( entry . name ) ;
21432149 switch ( keywordFilter ) {
21442150 case KeywordCompletionFilters . None :
2145- return getAllKeywordCompletions ( ) ;
2151+ // "undefined" is a global variable, so don't need a keyword completion for it.
2152+ return kind !== SyntaxKind . UndefinedKeyword ;
21462153 case KeywordCompletionFilters . ClassElementKeywords :
2147- return getFilteredKeywordCompletions ( isClassMemberCompletionKeywordText ) ;
2154+ return isClassMemberCompletionKeyword ( kind ) ;
21482155 case KeywordCompletionFilters . ConstructorParameterKeywords :
2149- return getFilteredKeywordCompletions ( isConstructorParameterCompletionKeywordText ) ;
2156+ return isConstructorParameterCompletionKeyword ( kind ) ;
21502157 case KeywordCompletionFilters . FunctionLikeBodyKeywords :
2151- return getFilteredKeywordCompletions ( isFunctionLikeBodyCompletionKeywordText ) ;
2158+ return isFunctionLikeBodyCompletionKeyword ( kind ) ;
2159+ case KeywordCompletionFilters . TypeKeywords :
2160+ return isTypeKeyword ( kind ) ;
21522161 default :
2153- Debug . assertNever ( keywordFilter ) ;
2162+ return Debug . assertNever ( keywordFilter ) ;
21542163 }
2155- }
2156-
2157- function getAllKeywordCompletions ( ) {
2158- const allKeywordsCompletions : CompletionEntry [ ] = [ ] ;
2159- for ( let i = SyntaxKind . FirstKeyword ; i <= SyntaxKind . LastKeyword ; i ++ ) {
2160- // "undefined" is a global variable, so don't need a keyword completion for it.
2161- if ( i === SyntaxKind . UndefinedKeyword ) continue ;
2162- allKeywordsCompletions . push ( {
2163- name : tokenToString ( i ) ,
2164- kind : ScriptElementKind . keyword ,
2165- kindModifiers : ScriptElementKindModifier . none ,
2166- sortText : "0"
2167- } ) ;
2168- }
2169- return allKeywordsCompletions ;
2170- }
2171-
2172- function getFilteredKeywordCompletions ( filterFn : FilterKeywordCompletions ) {
2173- return filter (
2174- getKeywordCompletions ( KeywordCompletionFilters . None ) ,
2175- entry => filterFn ( entry . name )
2176- ) ;
2177- }
2164+ } ) ) ;
21782165 }
21792166
21802167 function isClassMemberCompletionKeyword ( kind : SyntaxKind ) {
@@ -2222,15 +2209,12 @@ namespace ts.Completions {
22222209 case SyntaxKind . AbstractKeyword :
22232210 case SyntaxKind . GetKeyword :
22242211 case SyntaxKind . SetKeyword :
2212+ case SyntaxKind . UndefinedKeyword :
22252213 return false ;
22262214 }
22272215 return true ;
22282216 }
22292217
2230- function isFunctionLikeBodyCompletionKeywordText ( text : string ) {
2231- return isFunctionLikeBodyCompletionKeyword ( stringToToken ( text ) ) ;
2232- }
2233-
22342218 function isEqualityOperatorKind ( kind : ts . SyntaxKind ) : kind is EqualityOperator {
22352219 switch ( kind ) {
22362220 case ts . SyntaxKind . EqualsEqualsEqualsToken :
0 commit comments