@@ -2666,7 +2666,7 @@ export function getCompletionEntriesFromSymbols(
2666
2666
includeSymbol = false ,
2667
2667
) : UniqueNameSet {
2668
2668
const start = timestamp ( ) ;
2669
- const variableOrParameterDeclaration = getVariableOrParameterDeclaration ( contextToken , location ) ;
2669
+ const closestSymbolDeclaration = getClosestSymbolDeclaration ( contextToken , location ) ;
2670
2670
const useSemicolons = probablyUsesSemicolons ( sourceFile ) ;
2671
2671
const typeChecker = program . getTypeChecker ( ) ;
2672
2672
// Tracks unique names.
@@ -2745,26 +2745,33 @@ export function getCompletionEntriesFromSymbols(
2745
2745
}
2746
2746
// Filter out variables from their own initializers
2747
2747
// `const a = /* no 'a' here */`
2748
- if ( tryCast ( variableOrParameterDeclaration , isVariableDeclaration ) && symbol . valueDeclaration === variableOrParameterDeclaration ) {
2748
+ if ( tryCast ( closestSymbolDeclaration , isVariableDeclaration ) && symbol . valueDeclaration === closestSymbolDeclaration ) {
2749
2749
return false ;
2750
2750
}
2751
2751
2752
- // Filter out parameters from their own initializers
2752
+ // Filter out current and latter parameters from defaults
2753
2753
// `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 ) { }`
2755
2755
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
+ }
2768
2775
}
2769
2776
}
2770
2777
@@ -6001,20 +6008,39 @@ function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression
6001
6008
return ! tryCast ( isExternalModuleReference ( specifier ) ? specifier . expression : specifier , isStringLiteralLike ) ?. text ;
6002
6009
}
6003
6010
6004
- function getVariableOrParameterDeclaration ( contextToken : Node | undefined , location : Node ) {
6011
+ function getClosestSymbolDeclaration ( contextToken : Node | undefined , location : Node ) {
6005
6012
if ( ! contextToken ) return ;
6006
6013
6007
- const possiblyParameterDeclaration = findAncestor ( contextToken , node =>
6014
+ let closestDeclaration = findAncestor ( contextToken , node =>
6008
6015
isFunctionBlock ( node ) || isArrowFunctionBody ( node ) || isBindingPattern ( node )
6009
6016
? "quit"
6010
6017
: ( ( isParameter ( node ) || isTypeParameterDeclaration ( node ) ) && ! isIndexSignatureDeclaration ( node . parent ) ) ) ;
6011
6018
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
+ }
6016
6032
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 ;
6018
6044
}
6019
6045
6020
6046
function isArrowFunctionBody ( node : Node ) {
0 commit comments