@@ -844,7 +844,7 @@ namespace ts.Completions {
844844 *
845845 * @returns true if 'symbols' was successfully populated; false otherwise.
846846 */
847- function tryGetObjectLikeCompletionSymbols ( objectLikeContainer : ObjectLiteralExpression | BindingPattern ) : boolean {
847+ function tryGetObjectLikeCompletionSymbols ( objectLikeContainer : ObjectLiteralExpression | ObjectBindingPattern ) : boolean {
848848 // We're looking up possible property names from contextual/inferred/declared type.
849849 isMemberCompletion = true ;
850850
@@ -860,41 +860,36 @@ namespace ts.Completions {
860860 typeMembers = typeChecker . getAllPossiblePropertiesOfType ( typeForObject ) ;
861861 existingMembers = ( < ObjectLiteralExpression > objectLikeContainer ) . properties ;
862862 }
863- else if ( objectLikeContainer . kind === SyntaxKind . ObjectBindingPattern ) {
863+ else {
864+ Debug . assert ( objectLikeContainer . kind === SyntaxKind . ObjectBindingPattern ) ;
864865 // We are *only* completing on properties from the type being destructured.
865866 isNewIdentifierLocation = false ;
866867
867868 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 ) ;
882880 }
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 ) ;
889883 }
890884 }
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 ;
893891 }
894892 }
895- else {
896- Debug . fail ( "Expected object literal or binding pattern, got " + objectLikeContainer . kind ) ;
897- }
898893
899894 if ( typeMembers && typeMembers . length > 0 ) {
900895 // Add filtered items to the completion list
@@ -1003,14 +998,14 @@ namespace ts.Completions {
1003998 * Returns the immediate owning object literal or binding pattern of a context token,
1004999 * on the condition that one exists and that the context implies completion should be given.
10051000 */
1006- function tryGetObjectLikeCompletionContainer ( contextToken : Node ) : ObjectLiteralExpression | BindingPattern {
1001+ function tryGetObjectLikeCompletionContainer ( contextToken : Node ) : ObjectLiteralExpression | ObjectBindingPattern {
10071002 if ( contextToken ) {
10081003 switch ( contextToken . kind ) {
10091004 case SyntaxKind . OpenBraceToken : // const x = { |
10101005 case SyntaxKind . CommaToken : // const x = { a: 0, |
10111006 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 ;
10141009 }
10151010 break ;
10161011 }
0 commit comments