@@ -2666,7 +2666,7 @@ export function getCompletionEntriesFromSymbols(
26662666 includeSymbol = false ,
26672667) : UniqueNameSet {
26682668 const start = timestamp ( ) ;
2669- const variableOrParameterDeclaration = getVariableOrParameterDeclaration ( contextToken , location ) ;
2669+ const closestSymbolDeclaration = getClosestSymbolDeclaration ( contextToken , location ) ;
26702670 const useSemicolons = probablyUsesSemicolons ( sourceFile ) ;
26712671 const typeChecker = program . getTypeChecker ( ) ;
26722672 // Tracks unique names.
@@ -2745,26 +2745,33 @@ export function getCompletionEntriesFromSymbols(
27452745 }
27462746 // Filter out variables from their own initializers
27472747 // `const a = /* no 'a' here */`
2748- if ( tryCast ( variableOrParameterDeclaration , isVariableDeclaration ) && symbol . valueDeclaration === variableOrParameterDeclaration ) {
2748+ if ( tryCast ( closestSymbolDeclaration , isVariableDeclaration ) && symbol . valueDeclaration === closestSymbolDeclaration ) {
27492749 return false ;
27502750 }
27512751
2752- // Filter out parameters from their own initializers
2752+ // Filter out current and latter parameters from defaults
27532753 // `function f(a = /* no 'a' and 'b' here */, b) { }` or
2754- // `function f<T = /* no 'T' here */>(a: T) { }`
2754+ // `function f<T = /* no 'T' and 'T2' here */>(a: T, b: T2 ) { }`
27552755 const symbolDeclaration = symbol . valueDeclaration ?? symbol . declarations ?. [ 0 ] ;
2756- if (
2757- variableOrParameterDeclaration && symbolDeclaration && (
2758- ( isTypeParameterDeclaration ( variableOrParameterDeclaration ) && isTypeParameterDeclaration ( symbolDeclaration ) ) ||
2759- ( isParameter ( variableOrParameterDeclaration ) && isParameter ( symbolDeclaration ) )
2760- )
2761- ) {
2762- const symbolDeclarationPos = symbolDeclaration . pos ;
2763- const parameters = isParameter ( variableOrParameterDeclaration ) ? variableOrParameterDeclaration . parent . parameters :
2764- isInferTypeNode ( variableOrParameterDeclaration . parent ) ? undefined :
2765- variableOrParameterDeclaration . parent . typeParameters ;
2766- if ( symbolDeclarationPos >= variableOrParameterDeclaration . pos && parameters && symbolDeclarationPos < parameters . end ) {
2767- return false ;
2756+ if ( closestSymbolDeclaration && symbolDeclaration ) {
2757+ if ( isParameter ( closestSymbolDeclaration ) && isParameter ( symbolDeclaration ) ) {
2758+ const parameters = closestSymbolDeclaration . parent . parameters ;
2759+ if ( symbolDeclaration . pos >= closestSymbolDeclaration . pos && symbolDeclaration . pos < parameters . end ) {
2760+ return false ;
2761+ }
2762+ }
2763+ else if ( isTypeParameterDeclaration ( closestSymbolDeclaration ) && isTypeParameterDeclaration ( symbolDeclaration ) ) {
2764+ if ( closestSymbolDeclaration === symbolDeclaration && contextToken ?. kind === SyntaxKind . ExtendsKeyword ) {
2765+ // filter out the directly self-recursive type parameters
2766+ // `type A<K extends /* no 'K' here*/> = K`
2767+ return false ;
2768+ }
2769+ if ( isInTypeParameterDefault ( contextToken ) && ! isInferTypeNode ( closestSymbolDeclaration . parent ) ) {
2770+ const typeParameters = closestSymbolDeclaration . parent . typeParameters ;
2771+ if ( typeParameters && symbolDeclaration . pos >= closestSymbolDeclaration . pos && symbolDeclaration . pos < typeParameters . end ) {
2772+ return false ;
2773+ }
2774+ }
27682775 }
27692776 }
27702777
@@ -6001,20 +6008,39 @@ function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression
60016008 return ! tryCast ( isExternalModuleReference ( specifier ) ? specifier . expression : specifier , isStringLiteralLike ) ?. text ;
60026009}
60036010
6004- function getVariableOrParameterDeclaration ( contextToken : Node | undefined , location : Node ) {
6011+ function getClosestSymbolDeclaration ( contextToken : Node | undefined , location : Node ) {
60056012 if ( ! contextToken ) return ;
60066013
6007- const possiblyParameterDeclaration = findAncestor ( contextToken , node =>
6014+ let closestDeclaration = findAncestor ( contextToken , node =>
60086015 isFunctionBlock ( node ) || isArrowFunctionBody ( node ) || isBindingPattern ( node )
60096016 ? "quit"
60106017 : ( ( isParameter ( node ) || isTypeParameterDeclaration ( node ) ) && ! isIndexSignatureDeclaration ( node . parent ) ) ) ;
60116018
6012- const possiblyVariableDeclaration = findAncestor ( location , node =>
6013- isFunctionBlock ( node ) || isArrowFunctionBody ( node ) || isBindingPattern ( node )
6014- ? "quit"
6015- : isVariableDeclaration ( node ) ) ;
6019+ if ( ! closestDeclaration ) {
6020+ closestDeclaration = findAncestor ( location , node =>
6021+ isFunctionBlock ( node ) || isArrowFunctionBody ( node ) || isBindingPattern ( node )
6022+ ? "quit"
6023+ : isVariableDeclaration ( node ) ) ;
6024+ }
6025+ return closestDeclaration as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined ;
6026+ }
6027+
6028+ function isInTypeParameterDefault ( contextToken : Node | undefined ) {
6029+ if ( ! contextToken ) {
6030+ return false ;
6031+ }
60166032
6017- return ( possiblyParameterDeclaration || possiblyVariableDeclaration ) as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined ;
6033+ let node = contextToken ;
6034+ let parent = contextToken . parent ;
6035+ while ( parent ) {
6036+ if ( isTypeParameterDeclaration ( parent ) ) {
6037+ return parent . default === node || node . kind === SyntaxKind . EqualsToken ;
6038+ }
6039+ node = parent ;
6040+ parent = parent . parent ;
6041+ }
6042+
6043+ return false ;
60186044}
60196045
60206046function isArrowFunctionBody ( node : Node ) {
0 commit comments