@@ -844,7 +844,7 @@ namespace ts.Completions {
844
844
*
845
845
* @returns true if 'symbols' was successfully populated; false otherwise.
846
846
*/
847
- function tryGetObjectLikeCompletionSymbols ( objectLikeContainer : ObjectLiteralExpression | BindingPattern ) : boolean {
847
+ function tryGetObjectLikeCompletionSymbols ( objectLikeContainer : ObjectLiteralExpression | ObjectBindingPattern ) : boolean {
848
848
// We're looking up possible property names from contextual/inferred/declared type.
849
849
isMemberCompletion = true ;
850
850
@@ -860,41 +860,36 @@ namespace ts.Completions {
860
860
typeMembers = typeChecker . getAllPossiblePropertiesOfType ( typeForObject ) ;
861
861
existingMembers = ( < ObjectLiteralExpression > objectLikeContainer ) . properties ;
862
862
}
863
- else if ( objectLikeContainer . kind === SyntaxKind . ObjectBindingPattern ) {
863
+ else {
864
+ Debug . assert ( objectLikeContainer . kind === SyntaxKind . ObjectBindingPattern ) ;
864
865
// We are *only* completing on properties from the type being destructured.
865
866
isNewIdentifierLocation = false ;
866
867
867
868
const rootDeclaration = getRootDeclaration ( objectLikeContainer . parent ) ;
868
- if ( isVariableLike ( rootDeclaration ) ) {
869
- // We don't want to complete using the type acquired by the shape
870
- // of the binding pattern; we are only interested in types acquired
871
- // through type declaration or inference.
872
- // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
873
- // type of parameter will flow in from the contextual type of the function
874
- let canGetType = ! ! ( rootDeclaration . initializer || rootDeclaration . type ) ;
875
- if ( ! canGetType && rootDeclaration . kind === SyntaxKind . Parameter ) {
876
- if ( isExpression ( rootDeclaration . parent ) ) {
877
- canGetType = ! ! typeChecker . getContextualType ( < Expression > rootDeclaration . parent ) ;
878
- }
879
- else if ( rootDeclaration . parent . kind === SyntaxKind . MethodDeclaration || rootDeclaration . parent . kind === SyntaxKind . SetAccessor ) {
880
- canGetType = isExpression ( rootDeclaration . parent . parent ) && ! ! typeChecker . getContextualType ( < Expression > rootDeclaration . parent . parent ) ;
881
- }
869
+ if ( ! isVariableLike ( rootDeclaration ) ) throw Debug . fail ( "Root declaration is not variable-like." ) ;
870
+
871
+ // We don't want to complete using the type acquired by the shape
872
+ // of the binding pattern; we are only interested in types acquired
873
+ // through type declaration or inference.
874
+ // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
875
+ // type of parameter will flow in from the contextual type of the function
876
+ let canGetType = rootDeclaration . initializer || rootDeclaration . type || rootDeclaration . parent . parent . kind === SyntaxKind . ForOfStatement ;
877
+ if ( ! canGetType && rootDeclaration . kind === SyntaxKind . Parameter ) {
878
+ if ( isExpression ( rootDeclaration . parent ) ) {
879
+ canGetType = ! ! typeChecker . getContextualType ( < Expression > rootDeclaration . parent ) ;
882
880
}
883
- if ( canGetType ) {
884
- const typeForObject = typeChecker . getTypeAtLocation ( objectLikeContainer ) ;
885
- if ( ! typeForObject ) return false ;
886
- // In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
887
- typeMembers = typeChecker . getPropertiesOfType ( typeForObject ) ;
888
- existingMembers = ( < ObjectBindingPattern > objectLikeContainer ) . elements ;
881
+ else if ( rootDeclaration . parent . kind === SyntaxKind . MethodDeclaration || rootDeclaration . parent . kind === SyntaxKind . SetAccessor ) {
882
+ canGetType = isExpression ( rootDeclaration . parent . parent ) && ! ! typeChecker . getContextualType ( < Expression > rootDeclaration . parent . parent ) ;
889
883
}
890
884
}
891
- else {
892
- Debug . fail ( "Root declaration is not variable-like." ) ;
885
+ if ( canGetType ) {
886
+ const typeForObject = typeChecker . getTypeAtLocation ( objectLikeContainer ) ;
887
+ if ( ! typeForObject ) return false ;
888
+ // In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
889
+ typeMembers = typeChecker . getPropertiesOfType ( typeForObject ) ;
890
+ existingMembers = ( < ObjectBindingPattern > objectLikeContainer ) . elements ;
893
891
}
894
892
}
895
- else {
896
- Debug . fail ( "Expected object literal or binding pattern, got " + objectLikeContainer . kind ) ;
897
- }
898
893
899
894
if ( typeMembers && typeMembers . length > 0 ) {
900
895
// Add filtered items to the completion list
@@ -1003,14 +998,14 @@ namespace ts.Completions {
1003
998
* Returns the immediate owning object literal or binding pattern of a context token,
1004
999
* on the condition that one exists and that the context implies completion should be given.
1005
1000
*/
1006
- function tryGetObjectLikeCompletionContainer ( contextToken : Node ) : ObjectLiteralExpression | BindingPattern {
1001
+ function tryGetObjectLikeCompletionContainer ( contextToken : Node ) : ObjectLiteralExpression | ObjectBindingPattern {
1007
1002
if ( contextToken ) {
1008
1003
switch ( contextToken . kind ) {
1009
1004
case SyntaxKind . OpenBraceToken : // const x = { |
1010
1005
case SyntaxKind . CommaToken : // const x = { a: 0, |
1011
1006
const parent = contextToken . parent ;
1012
- if ( parent && ( parent . kind === SyntaxKind . ObjectLiteralExpression || parent . kind === SyntaxKind . ObjectBindingPattern ) ) {
1013
- return < ObjectLiteralExpression | BindingPattern > parent ;
1007
+ if ( isObjectLiteralExpression ( parent ) || isObjectBindingPattern ( parent ) ) {
1008
+ return parent ;
1014
1009
}
1015
1010
break ;
1016
1011
}
0 commit comments