@@ -24,6 +24,8 @@ namespace ts.Completions {
24
24
TypeKeywords ,
25
25
}
26
26
27
+ const enum GlobalsSearch { Continue , Success , Fail }
28
+
27
29
export function getCompletionsAtPosition (
28
30
host : LanguageServiceHost ,
29
31
typeChecker : TypeChecker ,
@@ -1046,52 +1048,38 @@ namespace ts.Completions {
1046
1048
}
1047
1049
1048
1050
function tryGetGlobalSymbols ( ) : boolean {
1049
- let objectLikeContainer : ObjectLiteralExpression | BindingPattern ;
1050
- let namedImportsOrExports : NamedImportsOrExports ;
1051
- let classLikeContainer : ClassLikeDeclaration ;
1052
- let jsxContainer : JsxOpeningLikeElement ;
1053
-
1054
- if ( objectLikeContainer = tryGetObjectLikeCompletionContainer ( contextToken ) ) {
1055
- return tryGetObjectLikeCompletionSymbols ( objectLikeContainer ) ;
1056
- }
1057
-
1058
- if ( namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion ( contextToken ) ) {
1059
- // cursor is in an import clause
1060
- // try to show exported member for imported module
1061
- return tryGetImportOrExportClauseCompletionSymbols ( namedImportsOrExports ) ;
1062
- }
1063
-
1064
- if ( tryGetConstructorLikeCompletionContainer ( contextToken ) ) {
1065
- // no members, only keywords
1066
- completionKind = CompletionKind . None ;
1067
- // Declaring new property/method/accessor
1068
- isNewIdentifierLocation = true ;
1069
- // Has keywords for constructor parameter
1070
- keywordFilters = KeywordCompletionFilters . ConstructorParameterKeywords ;
1071
- return true ;
1072
- }
1073
-
1074
- if ( classLikeContainer = tryGetClassLikeCompletionContainer ( contextToken ) ) {
1075
- // cursor inside class declaration
1076
- getGetClassLikeCompletionSymbols ( classLikeContainer ) ;
1077
- return true ;
1078
- }
1079
-
1080
- if ( jsxContainer = tryGetContainingJsxElement ( contextToken ) ) {
1081
- let attrsType : Type ;
1082
- if ( ( jsxContainer . kind === SyntaxKind . JsxSelfClosingElement ) || ( jsxContainer . kind === SyntaxKind . JsxOpeningElement ) ) {
1083
- // Cursor is inside a JSX self-closing element or opening element
1084
- attrsType = typeChecker . getAllAttributesTypeFromJsxOpeningLikeElement ( jsxContainer ) ;
1051
+ const result : GlobalsSearch = tryGetObjectLikeCompletionSymbols ( )
1052
+ || tryGetImportOrExportClauseCompletionSymbols ( )
1053
+ || tryGetConstructorCompletion ( )
1054
+ || tryGetClassLikeCompletionSymbols ( )
1055
+ || tryGetJsxCompletionSymbols ( )
1056
+ || ( getGlobalCompletions ( ) , GlobalsSearch . Success ) ;
1057
+ return result === GlobalsSearch . Success ;
1058
+ }
1059
+
1060
+ function tryGetConstructorCompletion ( ) : GlobalsSearch {
1061
+ if ( ! tryGetConstructorLikeCompletionContainer ( contextToken ) ) return GlobalsSearch . Continue ;
1062
+ // no members, only keywords
1063
+ completionKind = CompletionKind . None ;
1064
+ // Declaring new property/method/accessor
1065
+ isNewIdentifierLocation = true ;
1066
+ // Has keywords for constructor parameter
1067
+ keywordFilters = KeywordCompletionFilters . ConstructorParameterKeywords ;
1068
+ return GlobalsSearch . Success ;
1069
+ }
1085
1070
1086
- if ( attrsType ) {
1087
- symbols = filterJsxAttributes ( typeChecker . getPropertiesOfType ( attrsType ) , jsxContainer . attributes . properties ) ;
1088
- completionKind = CompletionKind . MemberLike ;
1089
- isNewIdentifierLocation = false ;
1090
- return true ;
1091
- }
1092
- }
1093
- }
1071
+ function tryGetJsxCompletionSymbols ( ) : GlobalsSearch {
1072
+ const jsxContainer = tryGetContainingJsxElement ( contextToken ) ;
1073
+ // Cursor is inside a JSX self-closing element or opening element
1074
+ const attrsType = jsxContainer && typeChecker . getAllAttributesTypeFromJsxOpeningLikeElement ( jsxContainer ) ;
1075
+ if ( ! attrsType ) return GlobalsSearch . Continue ;
1076
+ symbols = filterJsxAttributes ( typeChecker . getPropertiesOfType ( attrsType ) , jsxContainer . attributes . properties ) ;
1077
+ completionKind = CompletionKind . MemberLike ;
1078
+ isNewIdentifierLocation = false ;
1079
+ return GlobalsSearch . Success ;
1080
+ }
1094
1081
1082
+ function getGlobalCompletions ( ) : void {
1095
1083
if ( tryGetFunctionLikeBodyCompletionContainer ( contextToken ) ) {
1096
1084
keywordFilters = KeywordCompletionFilters . FunctionLikeBodyKeywords ;
1097
1085
}
@@ -1155,8 +1143,6 @@ namespace ts.Completions {
1155
1143
getSymbolsFromOtherSourceFileExports ( symbols , previousToken && isIdentifier ( previousToken ) ? previousToken . text : "" , target ) ;
1156
1144
}
1157
1145
filterGlobalCompletion ( symbols ) ;
1158
-
1159
- return true ;
1160
1146
}
1161
1147
1162
1148
function isSnippetScope ( scopeNode : Node ) : boolean {
@@ -1434,7 +1420,10 @@ namespace ts.Completions {
1434
1420
*
1435
1421
* @returns true if 'symbols' was successfully populated; false otherwise.
1436
1422
*/
1437
- function tryGetObjectLikeCompletionSymbols ( objectLikeContainer : ObjectLiteralExpression | ObjectBindingPattern ) : boolean {
1423
+ function tryGetObjectLikeCompletionSymbols ( ) : GlobalsSearch | undefined {
1424
+ const objectLikeContainer = tryGetObjectLikeCompletionContainer ( contextToken ) ;
1425
+ if ( ! objectLikeContainer ) return GlobalsSearch . Continue ;
1426
+
1438
1427
// We're looking up possible property names from contextual/inferred/declared type.
1439
1428
completionKind = CompletionKind . ObjectPropertyDeclaration ;
1440
1429
@@ -1446,7 +1435,7 @@ namespace ts.Completions {
1446
1435
// other than those within the declared type.
1447
1436
isNewIdentifierLocation = true ;
1448
1437
const typeForObject = typeChecker . getContextualType ( objectLikeContainer ) ;
1449
- if ( ! typeForObject ) return false ;
1438
+ if ( ! typeForObject ) return GlobalsSearch . Fail ;
1450
1439
typeMembers = getPropertiesForCompletion ( typeForObject , typeChecker , /*isForAccess*/ false ) ;
1451
1440
existingMembers = objectLikeContainer . properties ;
1452
1441
}
@@ -1474,7 +1463,7 @@ namespace ts.Completions {
1474
1463
}
1475
1464
if ( canGetType ) {
1476
1465
const typeForObject = typeChecker . getTypeAtLocation ( objectLikeContainer ) ;
1477
- if ( ! typeForObject ) return false ;
1466
+ if ( ! typeForObject ) return GlobalsSearch . Fail ;
1478
1467
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
1479
1468
typeMembers = typeChecker . getPropertiesOfType ( typeForObject ) . filter ( ( symbol ) => ! ( getDeclarationModifierFlagsFromSymbol ( symbol ) & ModifierFlags . NonPublicAccessibilityModifier ) ) ;
1480
1469
existingMembers = objectLikeContainer . elements ;
@@ -1485,7 +1474,7 @@ namespace ts.Completions {
1485
1474
// Add filtered items to the completion list
1486
1475
symbols = filterObjectMembersList ( typeMembers , Debug . assertDefined ( existingMembers ) ) ;
1487
1476
}
1488
- return true ;
1477
+ return GlobalsSearch . Success ;
1489
1478
}
1490
1479
1491
1480
/**
@@ -1503,15 +1492,20 @@ namespace ts.Completions {
1503
1492
*
1504
1493
* @returns true if 'symbols' was successfully populated; false otherwise.
1505
1494
*/
1506
- function tryGetImportOrExportClauseCompletionSymbols ( namedImportsOrExports : NamedImportsOrExports ) : boolean {
1495
+ function tryGetImportOrExportClauseCompletionSymbols ( ) : GlobalsSearch {
1496
+ const namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion ( contextToken ) ;
1497
+ if ( ! namedImportsOrExports ) return undefined ;
1498
+
1499
+ // cursor is in an import clause
1500
+ // try to show exported member for imported module
1507
1501
const declarationKind = namedImportsOrExports . kind === SyntaxKind . NamedImports ?
1508
1502
SyntaxKind . ImportDeclaration :
1509
1503
SyntaxKind . ExportDeclaration ;
1510
1504
const importOrExportDeclaration = < ImportDeclaration | ExportDeclaration > getAncestor ( namedImportsOrExports , declarationKind ) ;
1511
1505
const moduleSpecifier = importOrExportDeclaration . moduleSpecifier ;
1512
1506
1513
1507
if ( ! moduleSpecifier ) {
1514
- return false ;
1508
+ return GlobalsSearch . Fail ;
1515
1509
}
1516
1510
1517
1511
completionKind = CompletionKind . MemberLike ;
@@ -1520,19 +1514,22 @@ namespace ts.Completions {
1520
1514
const moduleSpecifierSymbol = typeChecker . getSymbolAtLocation ( moduleSpecifier ) ;
1521
1515
if ( ! moduleSpecifierSymbol ) {
1522
1516
symbols = emptyArray ;
1523
- return true ;
1517
+ return GlobalsSearch . Fail ;
1524
1518
}
1525
1519
1526
1520
const exports = typeChecker . getExportsAndPropertiesOfModule ( moduleSpecifierSymbol ) ;
1527
1521
symbols = filterNamedImportOrExportCompletionItems ( exports , namedImportsOrExports . elements ) ;
1528
- return true ;
1522
+ return GlobalsSearch . Success ;
1529
1523
}
1530
1524
1531
1525
/**
1532
1526
* Aggregates relevant symbols for completion in class declaration
1533
1527
* Relevant symbols are stored in the captured 'symbols' variable.
1534
1528
*/
1535
- function getGetClassLikeCompletionSymbols ( classLikeDeclaration : ClassLikeDeclaration ) {
1529
+ function tryGetClassLikeCompletionSymbols ( ) : GlobalsSearch {
1530
+ const classLikeDeclaration = tryGetClassLikeCompletionContainer ( contextToken ) ;
1531
+ if ( ! classLikeDeclaration ) return GlobalsSearch . Continue ;
1532
+
1536
1533
// We're looking up possible property names from parent type.
1537
1534
completionKind = CompletionKind . MemberLike ;
1538
1535
// Declaring new property/method/accessor
@@ -1582,6 +1579,7 @@ namespace ts.Completions {
1582
1579
classElementModifierFlags ) ;
1583
1580
}
1584
1581
}
1582
+ return GlobalsSearch . Success ;
1585
1583
}
1586
1584
1587
1585
/**
0 commit comments