@@ -2892,33 +2892,36 @@ namespace ts {
2892
2892
log ( "getCompletionData: Get previous token 2: " + ( new Date ( ) . getTime ( ) - start ) ) ;
2893
2893
}
2894
2894
2895
- // Check if this is a valid completion location
2896
- if ( contextToken && isCompletionListBlocker ( contextToken ) ) {
2897
- log ( "Returning an empty list because completion was requested in an invalid position." ) ;
2898
- return undefined ;
2899
- }
2900
-
2901
- let options = program . getCompilerOptions ( ) ;
2902
- let jsx = options . jsx !== JsxEmit . None ;
2903
- let target = options . target ;
2904
-
2905
- // Find the node where completion is requested on, in the case of a completion after
2906
- // a dot, it is the member access expression other wise, it is a request for all
2907
- // visible symbols in the scope, and the node is the current location.
2895
+ // Find the node where completion is requested on.
2896
+ // Also determine whether we are trying to complete with members of that node
2897
+ // or attributes of a JSX tag.
2908
2898
let node = currentToken ;
2909
2899
let isRightOfDot = false ;
2910
2900
let isRightOfOpenTag = false ;
2911
2901
2912
2902
let location = getTouchingPropertyName ( sourceFile , position ) ;
2913
- if ( contextToken ) {
2914
- let kind = contextToken . kind ;
2915
- if ( kind === SyntaxKind . DotToken && contextToken . parent . kind === SyntaxKind . PropertyAccessExpression ) {
2916
- node = ( < PropertyAccessExpression > contextToken . parent ) . expression ;
2917
- isRightOfDot = true ;
2903
+ if ( contextToken ) {
2904
+ // Bail out if this is a known invalid completion location
2905
+ if ( isCompletionListBlocker ( contextToken ) ) {
2906
+ log ( "Returning an empty list because completion was requested in an invalid position." ) ;
2907
+ return undefined ;
2918
2908
}
2919
- else if ( kind === SyntaxKind . DotToken && contextToken . parent . kind === SyntaxKind . QualifiedName ) {
2920
- node = ( < QualifiedName > contextToken . parent ) . left ;
2921
- isRightOfDot = true ;
2909
+
2910
+ let { parent, kind } = contextToken ;
2911
+ if ( kind === SyntaxKind . DotToken ) {
2912
+ if ( parent . kind === SyntaxKind . PropertyAccessExpression ) {
2913
+ node = ( < PropertyAccessExpression > contextToken . parent ) . expression ;
2914
+ isRightOfDot = true ;
2915
+ }
2916
+ else if ( parent . kind === SyntaxKind . QualifiedName ) {
2917
+ node = ( < QualifiedName > contextToken . parent ) . left ;
2918
+ isRightOfDot = true ;
2919
+ }
2920
+ else {
2921
+ // There is nothing that precedes the dot, so this likely just a stray character
2922
+ // or leading into a '...' token. Just bail out instead.
2923
+ return undefined ;
2924
+ }
2922
2925
}
2923
2926
else if ( kind === SyntaxKind . LessThanToken && sourceFile . languageVariant === LanguageVariant . JSX ) {
2924
2927
isRightOfOpenTag = true ;
@@ -3097,11 +3100,11 @@ namespace ts {
3097
3100
return scope ;
3098
3101
}
3099
3102
3100
- function isCompletionListBlocker ( previousToken : Node ) : boolean {
3103
+ function isCompletionListBlocker ( contextToken : Node ) : boolean {
3101
3104
let start = new Date ( ) . getTime ( ) ;
3102
- let result = isInStringOrRegularExpressionOrTemplateLiteral ( previousToken ) ||
3103
- isIdentifierDefinitionLocation ( previousToken ) ||
3104
- isRightOfIllegalDot ( previousToken ) ;
3105
+ let result = isInStringOrRegularExpressionOrTemplateLiteral ( contextToken ) ||
3106
+ isIdentifierDefinitionLocation ( contextToken ) ||
3107
+ isDotOfNumericLiteral ( contextToken ) ;
3105
3108
log ( "getCompletionsAtPosition: isCompletionListBlocker: " + ( new Date ( ) . getTime ( ) - start ) ) ;
3106
3109
return result ;
3107
3110
}
@@ -3180,12 +3183,12 @@ namespace ts {
3180
3183
return false ;
3181
3184
}
3182
3185
3183
- function isInStringOrRegularExpressionOrTemplateLiteral ( previousToken : Node ) : boolean {
3184
- if ( previousToken . kind === SyntaxKind . StringLiteral
3185
- || previousToken . kind === SyntaxKind . RegularExpressionLiteral
3186
- || isTemplateLiteralKind ( previousToken . kind ) ) {
3187
- let start = previousToken . getStart ( ) ;
3188
- let end = previousToken . getEnd ( ) ;
3186
+ function isInStringOrRegularExpressionOrTemplateLiteral ( contextToken : Node ) : boolean {
3187
+ if ( contextToken . kind === SyntaxKind . StringLiteral
3188
+ || contextToken . kind === SyntaxKind . RegularExpressionLiteral
3189
+ || isTemplateLiteralKind ( contextToken . kind ) ) {
3190
+ let start = contextToken . getStart ( ) ;
3191
+ let end = contextToken . getEnd ( ) ;
3189
3192
3190
3193
// To be "in" one of these literals, the position has to be:
3191
3194
// 1. entirely within the token text.
@@ -3196,8 +3199,8 @@ namespace ts {
3196
3199
}
3197
3200
3198
3201
if ( position === end ) {
3199
- return ! ! ( < LiteralExpression > previousToken ) . isUnterminated ||
3200
- previousToken . kind === SyntaxKind . RegularExpressionLiteral ;
3202
+ return ! ! ( < LiteralExpression > contextToken ) . isUnterminated
3203
+ || contextToken . kind === SyntaxKind . RegularExpressionLiteral ;
3201
3204
}
3202
3205
}
3203
3206
@@ -3351,101 +3354,98 @@ namespace ts {
3351
3354
return false ;
3352
3355
}
3353
3356
3354
- function isIdentifierDefinitionLocation ( previousToken : Node ) : boolean {
3355
- if ( previousToken ) {
3356
- let containingNodeKind = previousToken . parent . kind ;
3357
- switch ( previousToken . kind ) {
3358
- case SyntaxKind . CommaToken :
3359
- return containingNodeKind === SyntaxKind . VariableDeclaration ||
3360
- containingNodeKind === SyntaxKind . VariableDeclarationList ||
3361
- containingNodeKind === SyntaxKind . VariableStatement ||
3362
- containingNodeKind === SyntaxKind . EnumDeclaration || // enum a { foo, |
3363
- isFunction ( containingNodeKind ) ||
3364
- containingNodeKind === SyntaxKind . ClassDeclaration || // class A<T, |
3365
- containingNodeKind === SyntaxKind . FunctionDeclaration || // function A<T, |
3366
- containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface A<T, |
3367
- containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [x, y|
3357
+ function isIdentifierDefinitionLocation ( contextToken : Node ) : boolean {
3358
+ let containingNodeKind = contextToken . parent . kind ;
3359
+ switch ( contextToken . kind ) {
3360
+ case SyntaxKind . CommaToken :
3361
+ return containingNodeKind === SyntaxKind . VariableDeclaration ||
3362
+ containingNodeKind === SyntaxKind . VariableDeclarationList ||
3363
+ containingNodeKind === SyntaxKind . VariableStatement ||
3364
+ containingNodeKind === SyntaxKind . EnumDeclaration || // enum a { foo, |
3365
+ isFunction ( containingNodeKind ) ||
3366
+ containingNodeKind === SyntaxKind . ClassDeclaration || // class A<T, |
3367
+ containingNodeKind === SyntaxKind . FunctionDeclaration || // function A<T, |
3368
+ containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface A<T, |
3369
+ containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [x, y|
3368
3370
3369
- case SyntaxKind . DotToken :
3370
- return containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [.|
3371
+ case SyntaxKind . DotToken :
3372
+ return containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [.|
3371
3373
3372
- case SyntaxKind . ColonToken :
3373
- return containingNodeKind === SyntaxKind . BindingElement ; // var {x :html|
3374
+ case SyntaxKind . ColonToken :
3375
+ return containingNodeKind === SyntaxKind . BindingElement ; // var {x :html|
3374
3376
3375
- case SyntaxKind . OpenBracketToken :
3376
- return containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [x|
3377
+ case SyntaxKind . OpenBracketToken :
3378
+ return containingNodeKind === SyntaxKind . ArrayBindingPattern ; // var [x|
3377
3379
3378
- case SyntaxKind . OpenParenToken :
3379
- return containingNodeKind === SyntaxKind . CatchClause ||
3380
- isFunction ( containingNodeKind ) ;
3381
-
3382
- case SyntaxKind . OpenBraceToken :
3383
- return containingNodeKind === SyntaxKind . EnumDeclaration || // enum a { |
3384
- containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface a { |
3385
- containingNodeKind === SyntaxKind . TypeLiteral ; // let x : { |
3386
-
3387
- case SyntaxKind . SemicolonToken :
3388
- return containingNodeKind === SyntaxKind . PropertySignature &&
3389
- previousToken . parent && previousToken . parent . parent &&
3390
- ( previousToken . parent . parent . kind === SyntaxKind . InterfaceDeclaration || // interface a { f; |
3391
- previousToken . parent . parent . kind === SyntaxKind . TypeLiteral ) ; // let x : { a; |
3392
-
3393
- case SyntaxKind . LessThanToken :
3394
- return containingNodeKind === SyntaxKind . ClassDeclaration || // class A< |
3395
- containingNodeKind === SyntaxKind . FunctionDeclaration || // function A< |
3396
- containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface A< |
3397
- isFunction ( containingNodeKind ) ;
3398
-
3399
- case SyntaxKind . StaticKeyword :
3400
- return containingNodeKind === SyntaxKind . PropertyDeclaration ;
3401
-
3402
- case SyntaxKind . DotDotDotToken :
3403
- return containingNodeKind === SyntaxKind . Parameter ||
3404
- containingNodeKind === SyntaxKind . Constructor ||
3405
- ( previousToken . parent && previousToken . parent . parent &&
3406
- previousToken . parent . parent . kind === SyntaxKind . ArrayBindingPattern ) ; // var [...z|
3407
-
3408
- case SyntaxKind . PublicKeyword :
3409
- case SyntaxKind . PrivateKeyword :
3410
- case SyntaxKind . ProtectedKeyword :
3411
- return containingNodeKind === SyntaxKind . Parameter ;
3412
-
3413
- case SyntaxKind . ClassKeyword :
3414
- case SyntaxKind . EnumKeyword :
3415
- case SyntaxKind . InterfaceKeyword :
3416
- case SyntaxKind . FunctionKeyword :
3417
- case SyntaxKind . VarKeyword :
3418
- case SyntaxKind . GetKeyword :
3419
- case SyntaxKind . SetKeyword :
3420
- case SyntaxKind . ImportKeyword :
3421
- case SyntaxKind . LetKeyword :
3422
- case SyntaxKind . ConstKeyword :
3423
- case SyntaxKind . YieldKeyword :
3424
- case SyntaxKind . TypeKeyword : // type htm|
3425
- return true ;
3426
- }
3380
+ case SyntaxKind . OpenParenToken :
3381
+ return containingNodeKind === SyntaxKind . CatchClause ||
3382
+ isFunction ( containingNodeKind ) ;
3383
+
3384
+ case SyntaxKind . OpenBraceToken :
3385
+ return containingNodeKind === SyntaxKind . EnumDeclaration || // enum a { |
3386
+ containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface a { |
3387
+ containingNodeKind === SyntaxKind . TypeLiteral ; // let x : { |
3388
+
3389
+ case SyntaxKind . SemicolonToken :
3390
+ return containingNodeKind === SyntaxKind . PropertySignature &&
3391
+ contextToken . parent && contextToken . parent . parent &&
3392
+ ( contextToken . parent . parent . kind === SyntaxKind . InterfaceDeclaration || // interface a { f; |
3393
+ contextToken . parent . parent . kind === SyntaxKind . TypeLiteral ) ; // let x : { a; |
3394
+
3395
+ case SyntaxKind . LessThanToken :
3396
+ return containingNodeKind === SyntaxKind . ClassDeclaration || // class A< |
3397
+ containingNodeKind === SyntaxKind . FunctionDeclaration || // function A< |
3398
+ containingNodeKind === SyntaxKind . InterfaceDeclaration || // interface A< |
3399
+ isFunction ( containingNodeKind ) ;
3400
+
3401
+ case SyntaxKind . StaticKeyword :
3402
+ return containingNodeKind === SyntaxKind . PropertyDeclaration ;
3403
+
3404
+ case SyntaxKind . DotDotDotToken :
3405
+ return containingNodeKind === SyntaxKind . Parameter ||
3406
+ ( contextToken . parent && contextToken . parent . parent &&
3407
+ contextToken . parent . parent . kind === SyntaxKind . ArrayBindingPattern ) ; // var [...z|
3408
+
3409
+ case SyntaxKind . PublicKeyword :
3410
+ case SyntaxKind . PrivateKeyword :
3411
+ case SyntaxKind . ProtectedKeyword :
3412
+ return containingNodeKind === SyntaxKind . Parameter ;
3413
+
3414
+ case SyntaxKind . ClassKeyword :
3415
+ case SyntaxKind . EnumKeyword :
3416
+ case SyntaxKind . InterfaceKeyword :
3417
+ case SyntaxKind . FunctionKeyword :
3418
+ case SyntaxKind . VarKeyword :
3419
+ case SyntaxKind . GetKeyword :
3420
+ case SyntaxKind . SetKeyword :
3421
+ case SyntaxKind . ImportKeyword :
3422
+ case SyntaxKind . LetKeyword :
3423
+ case SyntaxKind . ConstKeyword :
3424
+ case SyntaxKind . YieldKeyword :
3425
+ case SyntaxKind . TypeKeyword : // type htm|
3426
+ return true ;
3427
+ }
3427
3428
3428
- // Previous token may have been a keyword that was converted to an identifier.
3429
- switch ( previousToken . getText ( ) ) {
3430
- case "class" :
3431
- case "interface" :
3432
- case "enum" :
3433
- case "function" :
3434
- case "var" :
3435
- case "static" :
3436
- case "let" :
3437
- case "const" :
3438
- case "yield" :
3439
- return true ;
3440
- }
3429
+ // Previous token may have been a keyword that was converted to an identifier.
3430
+ switch ( contextToken . getText ( ) ) {
3431
+ case "class" :
3432
+ case "interface" :
3433
+ case "enum" :
3434
+ case "function" :
3435
+ case "var" :
3436
+ case "static" :
3437
+ case "let" :
3438
+ case "const" :
3439
+ case "yield" :
3440
+ return true ;
3441
3441
}
3442
3442
3443
3443
return false ;
3444
3444
}
3445
3445
3446
- function isRightOfIllegalDot ( previousToken : Node ) : boolean {
3447
- if ( previousToken && previousToken . kind === SyntaxKind . NumericLiteral ) {
3448
- let text = previousToken . getFullText ( ) ;
3446
+ function isDotOfNumericLiteral ( contextToken : Node ) : boolean {
3447
+ if ( contextToken . kind === SyntaxKind . NumericLiteral ) {
3448
+ let text = contextToken . getFullText ( ) ;
3449
3449
return text . charAt ( text . length - 1 ) === "." ;
3450
3450
}
3451
3451
0 commit comments