Skip to content

Commit 156015b

Browse files
committed
Add support for type alias types and type parameters
1 parent 9122ed3 commit 156015b

File tree

21 files changed

+1130
-49
lines changed

21 files changed

+1130
-49
lines changed

apps/api-extractor-model/src/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export {
3838
IApiParameterOptions,
3939
ApiParameterListMixin
4040
} from './mixins/ApiParameterListMixin';
41+
export {
42+
IApiTypeParameterOptions,
43+
IApiTypeParameterListMixinOptions,
44+
ApiTypeParameterListMixin
45+
} from './mixins/ApiTypeParameterListMixin';
4146
export {
4247
IApiItemContainerMixinOptions,
4348
ApiItemContainerMixin
@@ -54,6 +59,10 @@ export {
5459
IApiStaticMixinOptions,
5560
ApiStaticMixin
5661
} from './mixins/ApiStaticMixin';
62+
export {
63+
IApiNameMixinOptions,
64+
ApiNameMixin
65+
} from './mixins/ApiNameMixin';
5766
export {
5867
ExcerptTokenKind,
5968
IExcerptTokenRange,
@@ -143,6 +152,10 @@ export {
143152
IApiTypeAliasOptions,
144153
ApiTypeAlias
145154
} from './model/ApiTypeAlias';
155+
export {
156+
ITypeParameterOptions,
157+
TypeParameter
158+
} from './model/TypeParameter';
146159
export {
147160
IApiVariableOptions,
148161
ApiVariable
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.s
3+
4+
import { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem';
5+
import { IExcerptTokenRange } from './Excerpt';
6+
import { TypeParameter } from '../model/TypeParameter';
7+
import { InternalError } from '@microsoft/node-core-library';
8+
import { ApiDeclaredItem } from '../items/ApiDeclaredItem';
9+
10+
/**
11+
* Represents parameter information that is part of {@link IApiTypeParameterListMixinOptions}
12+
* @public
13+
*/
14+
export interface IApiTypeParameterOptions {
15+
typeParameterName: string;
16+
constraintTokenRange?: IExcerptTokenRange;
17+
defaultTypeTokenRange?: IExcerptTokenRange;
18+
}
19+
20+
/**
21+
* Constructor options for {@link (ApiTypeParameterListMixin:interface)}.
22+
* @public
23+
*/
24+
export interface IApiTypeParameterListMixinOptions extends IApiItemOptions {
25+
typeParameters?: IApiTypeParameterOptions[];
26+
}
27+
28+
export interface IApiTypeParameterListMixinJson extends IApiItemJson {
29+
typeParameters?: IApiTypeParameterOptions[];
30+
}
31+
32+
const _typeParameters: unique symbol = Symbol('ApiTypeParameterListMixin._typeParameters');
33+
34+
/**
35+
* The mixin base class for API items that can have type parameters.
36+
*
37+
* @remarks
38+
*
39+
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
40+
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
41+
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
42+
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
43+
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
44+
* the function that generates a subclass, an interface that describes the members of the subclass, and
45+
* a namespace containing static members of the class.
46+
*
47+
* @public
48+
*/
49+
// tslint:disable-next-line:interface-name
50+
export interface ApiTypeParameterListMixin extends ApiItem {
51+
/**
52+
* The type parameters.
53+
*/
54+
readonly typeParameters: ReadonlyArray<TypeParameter>;
55+
56+
serializeInto(jsonObject: Partial<IApiItemJson>): void;
57+
}
58+
59+
/**
60+
* Mixin function for {@link (ApiTypeParameterListMixin:interface)}.
61+
*
62+
* @param baseClass - The base class to be extended
63+
* @returns A child class that extends baseClass, adding the {@link (ApiTypeParameterListMixin:interface)}
64+
* functionality.
65+
*
66+
* @public
67+
*/
68+
export function ApiTypeParameterListMixin<TBaseClass extends IApiItemConstructor>(baseClass: TBaseClass):
69+
TBaseClass & (new (...args: any[]) => ApiTypeParameterListMixin) { // tslint:disable-line:no-any
70+
71+
abstract class MixedClass extends baseClass implements ApiTypeParameterListMixin {
72+
public readonly [_typeParameters]: TypeParameter[];
73+
74+
/** @override */
75+
public static onDeserializeInto(options: Partial<IApiTypeParameterListMixinOptions>,
76+
jsonObject: IApiTypeParameterListMixinJson): void {
77+
78+
baseClass.onDeserializeInto(options, jsonObject);
79+
80+
options.typeParameters = jsonObject.typeParameters || [];
81+
}
82+
83+
// tslint:disable-next-line:no-any
84+
constructor(...args: any[]) {
85+
super(...args);
86+
87+
const options: IApiTypeParameterListMixinOptions = args[0];
88+
89+
this[_typeParameters] = [];
90+
91+
if (this instanceof ApiDeclaredItem) {
92+
if (options.typeParameters) {
93+
for (const typeParameterOptions of options.typeParameters) {
94+
95+
const typeParameter: TypeParameter = new TypeParameter({
96+
name: typeParameterOptions.typeParameterName,
97+
constraintExcerpt: typeParameterOptions.constraintTokenRange &&
98+
this.buildExcerpt(typeParameterOptions.constraintTokenRange),
99+
defaultTypeExcerpt: typeParameterOptions.defaultTypeTokenRange &&
100+
this.buildExcerpt(typeParameterOptions.defaultTypeTokenRange),
101+
parent: this
102+
});
103+
104+
this[_typeParameters].push(typeParameter);
105+
}
106+
}
107+
} else {
108+
throw new InternalError('ApiTypeParameterListMixin expects a base class that inherits from ApiDeclaredItem');
109+
}
110+
}
111+
112+
public get typeParameters(): ReadonlyArray<TypeParameter> {
113+
return this[_typeParameters];
114+
}
115+
116+
/** @override */
117+
public serializeInto(jsonObject: Partial<IApiTypeParameterListMixinJson>): void {
118+
super.serializeInto(jsonObject);
119+
120+
const typeParameterObjects: IApiTypeParameterOptions[] = [];
121+
for (const typeParameter of this.typeParameters) {
122+
const typeParameterOptions: IApiTypeParameterOptions = {
123+
typeParameterName: typeParameter.name
124+
};
125+
if (typeParameter.constraintExcerpt) {
126+
typeParameterOptions.constraintTokenRange = typeParameter.constraintExcerpt.tokenRange;
127+
}
128+
if (typeParameter.defaultTypeExcerpt) {
129+
typeParameterOptions.defaultTypeTokenRange = typeParameter.defaultTypeExcerpt.tokenRange;
130+
}
131+
typeParameterObjects.push(typeParameterOptions);
132+
}
133+
134+
if (typeParameterObjects.length > 0) {
135+
jsonObject.typeParameters = typeParameterObjects;
136+
}
137+
}
138+
}
139+
140+
return MixedClass;
141+
}
142+
143+
/**
144+
* Static members for {@link (ApiTypeParameterListMixin:interface)}.
145+
* @public
146+
*/
147+
export namespace ApiTypeParameterListMixin {
148+
/**
149+
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiParameterListMixin` mixin.
150+
*
151+
* @remarks
152+
*
153+
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
154+
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
155+
* the TypeScript type system cannot invoke a runtime test.)
156+
*/
157+
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiTypeParameterListMixin {
158+
return apiItem.hasOwnProperty(_typeParameters);
159+
}
160+
}

apps/api-extractor-model/src/model/ApiCallSignature.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import { IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredIt
66
import { IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin';
77
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin';
88
import { IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin';
9+
import { IApiTypeParameterListMixinOptions, ApiTypeParameterListMixin } from '../mixins/ApiTypeParameterListMixin';
910

1011
/**
1112
* Constructor options for {@link ApiCallSignature}.
1213
* @public
1314
*/
1415
export interface IApiCallSignatureOptions extends
16+
IApiTypeParameterListMixinOptions,
1517
IApiParameterListMixinOptions,
1618
IApiReleaseTagMixinOptions,
1719
IApiReturnTypeMixinOptions,
@@ -47,7 +49,8 @@ export interface IApiCallSignatureOptions extends
4749
*
4850
* @public
4951
*/
50-
export class ApiCallSignature extends ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(ApiDeclaredItem))) {
52+
export class ApiCallSignature extends ApiTypeParameterListMixin(ApiParameterListMixin(ApiReleaseTagMixin(
53+
ApiReturnTypeMixin(ApiDeclaredItem)))) {
5154

5255
public static getCanonicalReference(overloadIndex: number): string {
5356
return `(:call,${overloadIndex})`;

apps/api-extractor-model/src/model/ApiClass.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { ApiReleaseTagMixin, IApiReleaseTagMixinOptions } from '../mixins/ApiRel
88
import { IExcerptTokenRange } from '../mixins/Excerpt';
99
import { HeritageType } from './HeritageType';
1010
import { IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin';
11+
import { ApiTypeParameterListMixin, IApiTypeParameterListMixinOptions, IApiTypeParameterListMixinJson
12+
} from '../mixins/ApiTypeParameterListMixin';
1113

1214
/**
1315
* Constructor options for {@link ApiClass}.
@@ -17,13 +19,16 @@ export interface IApiClassOptions extends
1719
IApiItemContainerMixinOptions,
1820
IApiNameMixinOptions,
1921
IApiReleaseTagMixinOptions,
20-
IApiDeclaredItemOptions {
22+
IApiDeclaredItemOptions,
23+
IApiTypeParameterListMixinOptions {
2124

2225
extendsTokenRange: IExcerptTokenRange | undefined;
2326
implementsTokenRanges: IExcerptTokenRange[];
2427
}
2528

26-
export interface IApiClassJson extends IApiDeclaredItemJson {
29+
export interface IApiClassJson extends
30+
IApiDeclaredItemJson,
31+
IApiTypeParameterListMixinJson {
2732
extendsTokenRange?: IExcerptTokenRange;
2833
implementsTokenRanges: IExcerptTokenRange[];
2934
}
@@ -44,7 +49,8 @@ export interface IApiClassJson extends IApiDeclaredItemJson {
4449
*
4550
* @public
4651
*/
47-
export class ApiClass extends ApiItemContainerMixin(ApiNameMixin(ApiReleaseTagMixin(ApiDeclaredItem))) {
52+
export class ApiClass extends ApiItemContainerMixin(ApiNameMixin(ApiTypeParameterListMixin(ApiReleaseTagMixin(
53+
ApiDeclaredItem)))) {
4854

4955
/**
5056
* The base class that this class inherits from (using the `extends` keyword), or undefined if there is no base class.

apps/api-extractor-model/src/model/ApiConstructSignature.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import { IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredIt
66
import { IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin';
77
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin';
88
import { IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin';
9+
import { ApiTypeParameterListMixin, IApiTypeParameterListMixinOptions } from '../mixins/ApiTypeParameterListMixin';
910

1011
/**
1112
* Constructor options for {@link ApiConstructor}.
1213
* @public
1314
*/
1415
export interface IApiConstructSignatureOptions extends
16+
IApiTypeParameterListMixinOptions,
1517
IApiParameterListMixinOptions,
1618
IApiReleaseTagMixinOptions,
1719
IApiReturnTypeMixinOptions,
@@ -60,8 +62,8 @@ export interface IApiConstructSignatureOptions extends
6062
*
6163
* @public
6264
*/
63-
export class ApiConstructSignature extends ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(
64-
ApiDeclaredItem))) {
65+
export class ApiConstructSignature extends ApiTypeParameterListMixin(ApiParameterListMixin(ApiReleaseTagMixin(
66+
ApiReturnTypeMixin(ApiDeclaredItem)))) {
6567

6668
public static getCanonicalReference(overloadIndex: number): string {
6769
return `(:new,${overloadIndex})`;

apps/api-extractor-model/src/model/ApiFunction.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import { IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/
77
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin';
88
import { IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin';
99
import { IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin';
10+
import { IApiTypeParameterListMixinOptions, ApiTypeParameterListMixin } from '../mixins/ApiTypeParameterListMixin';
1011

1112
/**
1213
* Constructor options for {@link ApiFunction}.
1314
* @public
1415
*/
1516
export interface IApiFunctionOptions extends
1617
IApiNameMixinOptions,
18+
IApiTypeParameterListMixinOptions,
1719
IApiParameterListMixinOptions,
1820
IApiReleaseTagMixinOptions,
1921
IApiReturnTypeMixinOptions,
@@ -41,8 +43,8 @@ export interface IApiFunctionOptions extends
4143
*
4244
* @public
4345
*/
44-
export class ApiFunction extends ApiNameMixin(ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(
45-
ApiDeclaredItem)))) {
46+
export class ApiFunction extends ApiNameMixin(ApiTypeParameterListMixin(ApiParameterListMixin(ApiReleaseTagMixin(
47+
ApiReturnTypeMixin(ApiDeclaredItem))))) {
4648

4749
public static getCanonicalReference(name: string, overloadIndex: number): string {
4850
return `(${name}:${overloadIndex})`;

apps/api-extractor-model/src/model/ApiInterface.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
// See LICENSE in the project root for license information.
33

44
import { ApiItemKind } from '../items/ApiItem';
5-
import { ApiItemContainerMixin, IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin';
5+
import { ApiItemContainerMixin, IApiItemContainerMixinOptions, IApiItemContainerJson
6+
} from '../mixins/ApiItemContainerMixin';
67
import { ApiDeclaredItem, IApiDeclaredItemOptions, IApiDeclaredItemJson } from '../items/ApiDeclaredItem';
7-
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin';
8+
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin, IApiReleaseTagMixinJson } from '../mixins/ApiReleaseTagMixin';
89
import { IExcerptTokenRange } from '../mixins/Excerpt';
910
import { HeritageType } from './HeritageType';
10-
import { IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin';
11+
import { IApiNameMixinOptions, ApiNameMixin, IApiNameMixinJson } from '../mixins/ApiNameMixin';
12+
import { IApiTypeParameterListMixinOptions, IApiTypeParameterListMixinJson, ApiTypeParameterListMixin
13+
} from '../mixins/ApiTypeParameterListMixin';
1114

1215
/**
1316
* Constructor options for {@link ApiInterface}.
@@ -16,13 +19,20 @@ import { IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin';
1619
export interface IApiInterfaceOptions extends
1720
IApiItemContainerMixinOptions,
1821
IApiNameMixinOptions,
22+
IApiTypeParameterListMixinOptions,
1923
IApiReleaseTagMixinOptions,
2024
IApiDeclaredItemOptions {
2125

2226
extendsTokenRanges: IExcerptTokenRange[];
2327
}
2428

25-
export interface IApiInterfaceJson extends IApiDeclaredItemJson {
29+
export interface IApiInterfaceJson extends
30+
IApiItemContainerJson,
31+
IApiNameMixinJson,
32+
IApiTypeParameterListMixinJson,
33+
IApiReleaseTagMixinJson,
34+
IApiDeclaredItemJson {
35+
2636
extendsTokenRanges: IExcerptTokenRange[];
2737
}
2838

@@ -43,7 +53,8 @@ export interface IApiInterfaceJson extends IApiDeclaredItemJson {
4353
*
4454
* @public
4555
*/
46-
export class ApiInterface extends ApiItemContainerMixin(ApiNameMixin(ApiReleaseTagMixin(ApiDeclaredItem))) {
56+
export class ApiInterface extends ApiItemContainerMixin(ApiNameMixin(ApiTypeParameterListMixin(ApiReleaseTagMixin(
57+
ApiDeclaredItem)))) {
4758

4859
private readonly _extendsTypes: HeritageType[] = [];
4960

apps/api-extractor-model/src/model/ApiMethod.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/
88
import { IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin';
99
import { ApiReturnTypeMixin, IApiReturnTypeMixinOptions } from '../mixins/ApiReturnTypeMixin';
1010
import { IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin';
11+
import { ApiTypeParameterListMixin, IApiTypeParameterListMixinOptions } from '../mixins/ApiTypeParameterListMixin';
1112

1213
/**
1314
* Constructor options for {@link ApiMethod}.
1415
* @public
1516
*/
1617
export interface IApiMethodOptions extends
1718
IApiNameMixinOptions,
19+
IApiTypeParameterListMixinOptions,
1820
IApiParameterListMixinOptions,
1921
IApiReleaseTagMixinOptions,
2022
IApiReturnTypeMixinOptions,
@@ -43,8 +45,8 @@ export interface IApiMethodOptions extends
4345
*
4446
* @public
4547
*/
46-
export class ApiMethod extends ApiNameMixin(ApiParameterListMixin(ApiReleaseTagMixin(
47-
ApiReturnTypeMixin(ApiStaticMixin(ApiDeclaredItem))))) {
48+
export class ApiMethod extends ApiNameMixin(ApiTypeParameterListMixin(ApiParameterListMixin(
49+
ApiReleaseTagMixin(ApiReturnTypeMixin(ApiStaticMixin(ApiDeclaredItem)))))) {
4850

4951
public static getCanonicalReference(name: string, isStatic: boolean, overloadIndex: number): string {
5052
if (isStatic) {

0 commit comments

Comments
 (0)