@@ -2360,7 +2360,7 @@ namespace ts.Completions {
2360
2360
return isFunctionLike ( contextToken . parent ) && ! isMethodDeclaration ( contextToken . parent ) ;
2361
2361
}
2362
2362
2363
- // If the previous token is keyword correspoding to class member completion keyword
2363
+ // If the previous token is keyword corresponding to class member completion keyword
2364
2364
// there will be completion available here
2365
2365
if ( isClassMemberCompletionKeyword ( keywordForNode ( contextToken ) ) && isFromObjectTypeDeclaration ( contextToken ) ) {
2366
2366
return false ;
@@ -2398,6 +2398,33 @@ namespace ts.Completions {
2398
2398
return isPropertyDeclaration ( contextToken . parent ) ;
2399
2399
}
2400
2400
2401
+ // If we are inside a class declaration, and `constructor` is totally not present,
2402
+ // but we request a completion manually at a whitespace...
2403
+ const ancestorClassLike = findAncestor ( contextToken . parent , isClassLike ) ;
2404
+ if ( ancestorClassLike && contextToken === previousToken && isPreviousPropertyDeclarationTerminated ( contextToken , position ) ) {
2405
+ return false ; // Don't block completions.
2406
+ }
2407
+
2408
+ const ancestorPropertyDeclaraion = getAncestor ( contextToken . parent , SyntaxKind . PropertyDeclaration ) ;
2409
+ // If we are inside a class declaration and typing `constructor` after property declaration...
2410
+ if ( ancestorPropertyDeclaraion
2411
+ && contextToken !== previousToken
2412
+ && isClassLike ( previousToken . parent . parent )
2413
+ // And the cursor is at the token...
2414
+ && position <= previousToken . end ) {
2415
+ // If we are sure that the previous property declaration is terminated according to newline or semicolon...
2416
+ if ( isPreviousPropertyDeclarationTerminated ( contextToken , previousToken . end ) ) {
2417
+ return false ; // Don't block completions.
2418
+ }
2419
+ else if ( contextToken . kind !== SyntaxKind . EqualsToken
2420
+ // Should not block: `class C { blah = c/**/ }`
2421
+ // But should block: `class C { blah = somewhat c/**/ }` and `class C { blah: SomeType c/**/ }`
2422
+ && ( isInitializedProperty ( ancestorPropertyDeclaraion as PropertyDeclaration )
2423
+ || hasType ( ancestorPropertyDeclaraion ) ) ) {
2424
+ return true ;
2425
+ }
2426
+ }
2427
+
2401
2428
return isDeclarationName ( contextToken )
2402
2429
&& ! isShorthandPropertyAssignment ( contextToken . parent )
2403
2430
&& ! isJsxAttribute ( contextToken . parent )
@@ -2406,6 +2433,12 @@ namespace ts.Completions {
2406
2433
&& ! ( isClassLike ( contextToken . parent ) && ( contextToken !== previousToken || position > previousToken . end ) ) ;
2407
2434
}
2408
2435
2436
+ function isPreviousPropertyDeclarationTerminated ( contextToken : Node , position : number ) {
2437
+ return contextToken . kind !== SyntaxKind . EqualsToken &&
2438
+ ( contextToken . kind === SyntaxKind . SemicolonToken
2439
+ || ! positionsAreOnSameLine ( contextToken . end , position , sourceFile ) ) ;
2440
+ }
2441
+
2409
2442
function isFunctionLikeButNotConstructor ( kind : SyntaxKind ) {
2410
2443
return isFunctionLikeKind ( kind ) && kind !== SyntaxKind . Constructor ;
2411
2444
}
@@ -2859,6 +2892,13 @@ namespace ts.Completions {
2859
2892
2860
2893
if ( ! contextToken ) return undefined ;
2861
2894
2895
+ // class C { blah; constructor/**/ } and so on
2896
+ if ( location . kind === SyntaxKind . ConstructorKeyword
2897
+ // class C { blah \n constructor/**/ }
2898
+ || ( isIdentifier ( contextToken ) && isPropertyDeclaration ( contextToken . parent ) && isClassLike ( location ) ) ) {
2899
+ return findAncestor ( contextToken , isClassLike ) as ObjectTypeDeclaration ;
2900
+ }
2901
+
2862
2902
switch ( contextToken . kind ) {
2863
2903
case SyntaxKind . EqualsToken : // class c { public prop = | /* global completions */ }
2864
2904
return undefined ;
0 commit comments