Skip to content

Commit b68fec6

Browse files
committed
Handle some Members navigation step edge cases
1 parent d61f74f commit b68fec6

File tree

7 files changed

+230
-30
lines changed

7 files changed

+230
-30
lines changed

apps/api-extractor/src/generators/DeclarationReferenceGenerator.ts

+24-10
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,27 @@ export class DeclarationReferenceGenerator {
9292
const sourceFile: ts.SourceFile | undefined = declaration?.getSourceFile();
9393
const parent: ts.Symbol | undefined = TypeScriptInternals.getSymbolParent(symbol);
9494

95-
// If it's a global, then use an Exports navigation.
96-
if (sourceFile && !ts.isExternalModule(sourceFile)) {
97-
return Navigation.Exports;
98-
}
95+
// If it's global or from an external library, then use either Members or Exports. It's not possible for
96+
// global symbols or external library symbols to be Locals.
97+
const isGlobal: boolean = !!sourceFile && !ts.isExternalModule(sourceFile);
98+
const isFromExternalLibrary: boolean =
99+
!!sourceFile && this._collector.program.isSourceFileFromExternalLibrary(sourceFile);
100+
if (isGlobal || isFromExternalLibrary) {
101+
if (
102+
parent &&
103+
parent.members &&
104+
DeclarationReferenceGenerator._isSameSymbol(parent.members.get(symbol.escapedName), symbol)
105+
) {
106+
return Navigation.Members;
107+
}
99108

100-
// If it's from an external library, then use an Exports navigation.
101-
if (sourceFile && this._collector.program.isSourceFileFromExternalLibrary(sourceFile)) {
102109
return Navigation.Exports;
103110
}
104111

105112
// Otherwise, this symbol is from the current package.
106113
if (parent) {
107114
// If we've found an exported CollectorEntity, then it's exported from the package entry point, so
108-
// use an Exports navigation.
115+
// use Exports.
109116
const namedDeclaration: ts.DeclarationName | undefined = (
110117
declaration as ts.NamedDeclaration | undefined
111118
)?.name;
@@ -117,10 +124,17 @@ export class DeclarationReferenceGenerator {
117124
}
118125
}
119126

120-
// If its parent symbol is not a source file, then use an Exports navigation. If the parent symbol is
121-
// a source file, but it wasn't exported from the package entry point (in the check above), then the symbol
122-
// is a local, so fall through below.
127+
// If its parent symbol is not a source file, then use either Exports or Members. If the parent symbol
128+
// is a source file, but it wasn't exported from the package entry point (in the check above), then the
129+
// symbol is a local, so fall through below.
123130
if (!DeclarationReferenceGenerator._isExternalModuleSymbol(parent)) {
131+
if (
132+
parent.members &&
133+
DeclarationReferenceGenerator._isSameSymbol(parent.members.get(symbol.escapedName), symbol)
134+
) {
135+
return Navigation.Members;
136+
}
137+
124138
return Navigation.Exports;
125139
}
126140
}

build-tests/api-extractor-lib2-test/etc/api-extractor-lib2-test.api.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
// @public (undocumented)
88
class DefaultClass {
99
}
10-
1110
export default DefaultClass;
1211

1312
// @public (undocumented)
1413
export class Lib2Class {
14+
// (undocumented)
15+
prop: number;
1516
}
1617

1718
// @alpha (undocumented)
1819
export interface Lib2Interface {
1920
}
2021

21-
2222
```

build-tests/api-extractor-lib2-test/src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
*/
1212

1313
/** @public */
14-
export class Lib2Class {}
14+
export class Lib2Class {
15+
prop: number;
16+
}
1517

1618
/** @alpha */
1719
export interface Lib2Interface {}

build-tests/api-extractor-scenarios/etc/referenceTokens/api-extractor-scenarios.api.json

+163-8
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,16 @@
629629
"excerptTokens": [
630630
{
631631
"kind": "Content",
632-
"text": "export declare function someFunction7(): "
632+
"text": "export declare function someFunction7({ "
633+
},
634+
{
635+
"kind": "Reference",
636+
"text": "then",
637+
"canonicalReference": "!Promise#then"
638+
},
639+
{
640+
"kind": "Content",
641+
"text": ": then2 }: "
633642
},
634643
{
635644
"kind": "Reference",
@@ -640,18 +649,40 @@
640649
"kind": "Content",
641650
"text": "<void>"
642651
},
652+
{
653+
"kind": "Content",
654+
"text": "): "
655+
},
656+
{
657+
"kind": "Content",
658+
"text": "typeof "
659+
},
660+
{
661+
"kind": "Reference",
662+
"text": "Date.prototype.getDate",
663+
"canonicalReference": "!Date#getDate:member"
664+
},
643665
{
644666
"kind": "Content",
645667
"text": ";"
646668
}
647669
],
648670
"returnTypeTokenRange": {
649-
"startIndex": 1,
650-
"endIndex": 3
671+
"startIndex": 6,
672+
"endIndex": 8
651673
},
652674
"releaseTag": "Public",
653675
"overloadIndex": 1,
654-
"parameters": [],
676+
"parameters": [
677+
{
678+
"parameterName": "{ then: then2 }",
679+
"parameterTypeTokenRange": {
680+
"startIndex": 3,
681+
"endIndex": 5
682+
},
683+
"isOptional": false
684+
}
685+
],
655686
"name": "someFunction7"
656687
},
657688
{
@@ -661,26 +692,150 @@
661692
"excerptTokens": [
662693
{
663694
"kind": "Content",
664-
"text": "export declare function someFunction8(): "
695+
"text": "export declare function someFunction8({ "
696+
},
697+
{
698+
"kind": "Reference",
699+
"text": "prop",
700+
"canonicalReference": "api-extractor-lib2-test!Lib2Class#prop"
701+
},
702+
{
703+
"kind": "Content",
704+
"text": ": prop2 }: "
665705
},
666706
{
667707
"kind": "Reference",
668708
"text": "Lib2Class",
669709
"canonicalReference": "api-extractor-lib2-test!Lib2Class:class"
670710
},
711+
{
712+
"kind": "Content",
713+
"text": "): "
714+
},
715+
{
716+
"kind": "Content",
717+
"text": "void"
718+
},
671719
{
672720
"kind": "Content",
673721
"text": ";"
674722
}
675723
],
676724
"returnTypeTokenRange": {
677-
"startIndex": 1,
678-
"endIndex": 2
725+
"startIndex": 5,
726+
"endIndex": 6
679727
},
680728
"releaseTag": "Public",
681729
"overloadIndex": 1,
682-
"parameters": [],
730+
"parameters": [
731+
{
732+
"parameterName": "{ prop: prop2 }",
733+
"parameterTypeTokenRange": {
734+
"startIndex": 3,
735+
"endIndex": 4
736+
},
737+
"isOptional": false
738+
}
739+
],
683740
"name": "someFunction8"
741+
},
742+
{
743+
"kind": "Function",
744+
"canonicalReference": "api-extractor-scenarios!someFunction9:function(1)",
745+
"docComment": "/**\n * Interface member reference.\n *\n * @public\n */\n",
746+
"excerptTokens": [
747+
{
748+
"kind": "Content",
749+
"text": "export declare function someFunction9({ "
750+
},
751+
{
752+
"kind": "Reference",
753+
"text": "prop",
754+
"canonicalReference": "api-extractor-scenarios!SomeInterface1#prop"
755+
},
756+
{
757+
"kind": "Content",
758+
"text": ": prop2 }: "
759+
},
760+
{
761+
"kind": "Reference",
762+
"text": "SomeInterface1",
763+
"canonicalReference": "api-extractor-scenarios!SomeInterface1:interface"
764+
},
765+
{
766+
"kind": "Content",
767+
"text": "): "
768+
},
769+
{
770+
"kind": "Content",
771+
"text": "void"
772+
},
773+
{
774+
"kind": "Content",
775+
"text": ";"
776+
}
777+
],
778+
"returnTypeTokenRange": {
779+
"startIndex": 5,
780+
"endIndex": 6
781+
},
782+
"releaseTag": "Public",
783+
"overloadIndex": 1,
784+
"parameters": [
785+
{
786+
"parameterName": "{ prop: prop2 }",
787+
"parameterTypeTokenRange": {
788+
"startIndex": 3,
789+
"endIndex": 4
790+
},
791+
"isOptional": false
792+
}
793+
],
794+
"name": "someFunction9"
795+
},
796+
{
797+
"kind": "Interface",
798+
"canonicalReference": "api-extractor-scenarios!SomeInterface1:interface",
799+
"docComment": "/**\n * @public\n */\n",
800+
"excerptTokens": [
801+
{
802+
"kind": "Content",
803+
"text": "export interface SomeInterface1 "
804+
}
805+
],
806+
"releaseTag": "Public",
807+
"name": "SomeInterface1",
808+
"preserveMemberOrder": false,
809+
"members": [
810+
{
811+
"kind": "PropertySignature",
812+
"canonicalReference": "api-extractor-scenarios!SomeInterface1#prop:member",
813+
"docComment": "",
814+
"excerptTokens": [
815+
{
816+
"kind": "Content",
817+
"text": "prop: "
818+
},
819+
{
820+
"kind": "Content",
821+
"text": "number"
822+
},
823+
{
824+
"kind": "Content",
825+
"text": ";"
826+
}
827+
],
828+
"isReadonly": false,
829+
"isOptional": false,
830+
"releaseTag": "Public",
831+
"name": "prop",
832+
"propertyTypeTokenRange": {
833+
"startIndex": 1,
834+
"endIndex": 2
835+
}
836+
}
837+
],
838+
"extendsTokenRanges": []
684839
}
685840
]
686841
}

build-tests/api-extractor-scenarios/etc/referenceTokens/api-extractor-scenarios.api.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,19 @@ export function someFunction5(): SomeEnum.A;
6565
export function someFunction6(): typeof SomeClass1.staticProp;
6666

6767
// @public
68-
export function someFunction7(): Promise<void>;
68+
export function someFunction7({ then: then2 }: Promise<void>): typeof Date.prototype.getDate;
6969

7070
// @public
71-
export function someFunction8(): Lib2Class;
71+
export function someFunction8({ prop: prop2 }: Lib2Class): void;
72+
73+
// @public
74+
export function someFunction9({ prop: prop2 }: SomeInterface1): void;
75+
76+
// @public (undocumented)
77+
export interface SomeInterface1 {
78+
// (undocumented)
79+
prop: number;
80+
}
7281

7382
// (No @packageDocumentation comment for this package)
7483

build-tests/api-extractor-scenarios/etc/referenceTokens/rollup.d.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,23 @@ export declare function someFunction6(): typeof SomeClass1.staticProp;
6767
* Global symbol reference.
6868
* @public
6969
*/
70-
export declare function someFunction7(): Promise<void>;
70+
export declare function someFunction7({ then: then2 }: Promise<void>): typeof Date.prototype.getDate;
7171

7272
/**
7373
* External symbol reference.
7474
* @public
7575
*/
76-
export declare function someFunction8(): Lib2Class;
76+
export declare function someFunction8({ prop: prop2 }: Lib2Class): void;
77+
78+
/**
79+
* Interface member reference.
80+
* @public
81+
*/
82+
export declare function someFunction9({ prop: prop2 }: SomeInterface1): void;
83+
84+
/** @public */
85+
export declare interface SomeInterface1 {
86+
prop: number;
87+
}
7788

7889
export { }

build-tests/api-extractor-scenarios/src/referenceTokens/index.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ export function someFunction6(): typeof SomeClass1.staticProp {
6464
return 5;
6565
}
6666

67+
/** @public */
68+
export interface SomeInterface1 {
69+
prop: number;
70+
}
71+
72+
/**
73+
* Interface member reference.
74+
* @public
75+
*/
76+
export function someFunction9({ prop: prop2 }: SomeInterface1): void {}
77+
6778
class SomeClass2 {}
6879

6980
/**
@@ -76,17 +87,15 @@ export class SomeClass3 extends SomeClass2 {}
7687
* Global symbol reference.
7788
* @public
7889
*/
79-
export function someFunction7(): Promise<void> {
80-
return Promise.resolve();
90+
export function someFunction7({ then: then2 }: Promise<void>): typeof Date.prototype.getDate {
91+
return () => 5;
8192
}
8293

8394
/**
8495
* External symbol reference.
8596
* @public
8697
*/
87-
export function someFunction8(): Lib2Class {
88-
return new Lib2Class();
89-
}
98+
export function someFunction8({ prop: prop2 }: Lib2Class): void {}
9099

91100
/**
92101
* Reference to a symbol exported from another file, but not exported from the package.

0 commit comments

Comments
 (0)