@@ -227,7 +227,7 @@ namespace ts {
227
227
symbol . flags |= symbolFlags ;
228
228
229
229
node . symbol = symbol ;
230
- symbol . declarations = append ( symbol . declarations , node ) ;
230
+ symbol . declarations = appendIfUnique ( symbol . declarations , node ) ;
231
231
232
232
if ( symbolFlags & ( SymbolFlags . Class | SymbolFlags . Enum | SymbolFlags . Module | SymbolFlags . Variable ) && ! symbol . exports ) {
233
233
symbol . exports = createSymbolTable ( ) ;
@@ -737,6 +737,9 @@ namespace ts {
737
737
case SyntaxKind . JSDocEnumTag :
738
738
bindJSDocTypeAlias ( node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag ) ;
739
739
break ;
740
+ case SyntaxKind . JSDocClassTag :
741
+ bindJSDocClassTag ( node as JSDocClassTag ) ;
742
+ break ;
740
743
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
741
744
case SyntaxKind . SourceFile : {
742
745
bindEachFunctionsFirst ( ( node as SourceFile ) . statements ) ;
@@ -1446,6 +1449,14 @@ namespace ts {
1446
1449
}
1447
1450
}
1448
1451
1452
+ function bindJSDocClassTag ( node : JSDocClassTag ) {
1453
+ bindEachChild ( node ) ;
1454
+ const host = getHostSignatureFromJSDoc ( node ) ;
1455
+ if ( host && host . kind !== SyntaxKind . MethodDeclaration ) {
1456
+ addDeclarationToSymbol ( host . symbol , host , SymbolFlags . Class ) ;
1457
+ }
1458
+ }
1459
+
1449
1460
function bindCallExpressionFlow ( node : CallExpression ) {
1450
1461
// If the target of the call expression is a function expression or arrow function we have
1451
1462
// an immediately invoked function expression (IIFE). Initialize the flowNode property to
@@ -1813,7 +1824,8 @@ namespace ts {
1813
1824
// typedef anchored to an A.B.C assignment - we need to bind into B's namespace under name C
1814
1825
const isTopLevel = isTopLevelNamespaceAssignment ( declName . parent ) ;
1815
1826
if ( isTopLevel ) {
1816
- bindPotentiallyMissingNamespaces ( file . symbol , declName . parent , isTopLevel , ! ! findAncestor ( declName , d => isPropertyAccessExpression ( d ) && d . name . escapedText === "prototype" ) ) ;
1827
+ bindPotentiallyMissingNamespaces ( file . symbol , declName . parent , isTopLevel ,
1828
+ ! ! findAncestor ( declName , d => isPropertyAccessExpression ( d ) && d . name . escapedText === "prototype" ) , /*containerIsClass*/ false ) ;
1817
1829
const oldContainer = container ;
1818
1830
container = isPropertyAccessExpression ( declName . parent . expression ) ? declName . parent . expression . name : declName . parent . expression ;
1819
1831
declareModuleMember ( typeAlias , SymbolFlags . TypeAlias , SymbolFlags . TypeAliasExcludes ) ;
@@ -2510,6 +2522,7 @@ namespace ts {
2510
2522
constructorSymbol . members = constructorSymbol . members || createSymbolTable ( ) ;
2511
2523
// It's acceptable for multiple 'this' assignments of the same identifier to occur
2512
2524
declareSymbol ( constructorSymbol . members , constructorSymbol , node , SymbolFlags . Property , SymbolFlags . PropertyExcludes & ~ SymbolFlags . Property ) ;
2525
+ addDeclarationToSymbol ( constructorSymbol , constructorSymbol . valueDeclaration , SymbolFlags . Class ) ;
2513
2526
}
2514
2527
break ;
2515
2528
@@ -2558,7 +2571,7 @@ namespace ts {
2558
2571
node . left . parent = node ;
2559
2572
node . right . parent = node ;
2560
2573
const lhs = node . left as PropertyAccessEntityNameExpression ;
2561
- bindPropertyAssignment ( lhs . expression , lhs , /*isPrototypeProperty*/ false ) ;
2574
+ bindPropertyAssignment ( lhs . expression , lhs , /*isPrototypeProperty*/ false , /*containerIsClass*/ true ) ;
2562
2575
}
2563
2576
2564
2577
function bindObjectDefinePrototypeProperty ( node : BindableObjectDefinePropertyCall ) {
@@ -2581,13 +2594,13 @@ namespace ts {
2581
2594
constructorFunction . parent = classPrototype ;
2582
2595
classPrototype . parent = lhs ;
2583
2596
2584
- bindPropertyAssignment ( constructorFunction , lhs , /*isPrototypeProperty*/ true ) ;
2597
+ bindPropertyAssignment ( constructorFunction , lhs , /*isPrototypeProperty*/ true , /*containerIsClass*/ true ) ;
2585
2598
}
2586
2599
2587
2600
function bindObjectDefinePropertyAssignment ( node : BindableObjectDefinePropertyCall ) {
2588
2601
let namespaceSymbol = lookupSymbolForPropertyAccess ( node . arguments [ 0 ] ) ;
2589
2602
const isToplevel = node . parent . parent . kind === SyntaxKind . SourceFile ;
2590
- namespaceSymbol = bindPotentiallyMissingNamespaces ( namespaceSymbol , node . arguments [ 0 ] , isToplevel , /*isPrototypeProperty*/ false ) ;
2603
+ namespaceSymbol = bindPotentiallyMissingNamespaces ( namespaceSymbol , node . arguments [ 0 ] , isToplevel , /*isPrototypeProperty*/ false , /*containerIsClass*/ false ) ;
2591
2604
bindPotentiallyNewExpandoMemberToNamespace ( node , namespaceSymbol , /*isPrototypeProperty*/ false ) ;
2592
2605
}
2593
2606
@@ -2618,10 +2631,10 @@ namespace ts {
2618
2631
*/
2619
2632
function bindStaticPropertyAssignment ( node : PropertyAccessEntityNameExpression ) {
2620
2633
node . expression . parent = node ;
2621
- bindPropertyAssignment ( node . expression , node , /*isPrototypeProperty*/ false ) ;
2634
+ bindPropertyAssignment ( node . expression , node , /*isPrototypeProperty*/ false , /*containerIsClass*/ false ) ;
2622
2635
}
2623
2636
2624
- function bindPotentiallyMissingNamespaces ( namespaceSymbol : Symbol | undefined , entityName : EntityNameExpression , isToplevel : boolean , isPrototypeProperty : boolean ) {
2637
+ function bindPotentiallyMissingNamespaces ( namespaceSymbol : Symbol | undefined , entityName : EntityNameExpression , isToplevel : boolean , isPrototypeProperty : boolean , containerIsClass : boolean ) {
2625
2638
if ( isToplevel && ! isPrototypeProperty ) {
2626
2639
// make symbols or add declarations for intermediate containers
2627
2640
const flags = SymbolFlags . Module | SymbolFlags . Assignment ;
@@ -2638,6 +2651,9 @@ namespace ts {
2638
2651
}
2639
2652
} ) ;
2640
2653
}
2654
+ if ( containerIsClass && namespaceSymbol ) {
2655
+ addDeclarationToSymbol ( namespaceSymbol , namespaceSymbol . valueDeclaration , SymbolFlags . Class ) ;
2656
+ }
2641
2657
return namespaceSymbol ;
2642
2658
}
2643
2659
@@ -2663,10 +2679,10 @@ namespace ts {
2663
2679
: propertyAccess . parent . parent . kind === SyntaxKind . SourceFile ;
2664
2680
}
2665
2681
2666
- function bindPropertyAssignment ( name : EntityNameExpression , propertyAccess : PropertyAccessEntityNameExpression , isPrototypeProperty : boolean ) {
2682
+ function bindPropertyAssignment ( name : EntityNameExpression , propertyAccess : PropertyAccessEntityNameExpression , isPrototypeProperty : boolean , containerIsClass : boolean ) {
2667
2683
let namespaceSymbol = lookupSymbolForPropertyAccess ( name ) ;
2668
2684
const isToplevel = isTopLevelNamespaceAssignment ( propertyAccess ) ;
2669
- namespaceSymbol = bindPotentiallyMissingNamespaces ( namespaceSymbol , propertyAccess . expression , isToplevel , isPrototypeProperty ) ;
2685
+ namespaceSymbol = bindPotentiallyMissingNamespaces ( namespaceSymbol , propertyAccess . expression , isToplevel , isPrototypeProperty , containerIsClass ) ;
2670
2686
bindPotentiallyNewExpandoMemberToNamespace ( propertyAccess , namespaceSymbol , isPrototypeProperty ) ;
2671
2687
}
2672
2688
0 commit comments