mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-12 09:33:32 +01:00
build: package api-extractor and -model (#9920)
* fix(ExceptText): don't display import("d..-types/v10"). in return type
* Squashed 'packages/api-extractor-model/' content from commit 39ecb196c
git-subtree-dir: packages/api-extractor-model
git-subtree-split: 39ecb196ca210bdf84ba6c9cadb1bb93571849d7
* Squashed 'packages/api-extractor/' content from commit 341ad6c51
git-subtree-dir: packages/api-extractor
git-subtree-split: 341ad6c51b01656d4f73b74ad4bdb3095f9262c4
* feat(api-extractor): add api-extractor and -model
* fix: package.json docs script
* fix(SourcLink): use <> instead of function syntax
* fix: make packages private
* fix: rest params showing in docs, added labels
* fix: missed two files
* fix: cpy-cli & pnpm-lock
* fix: increase icon size
* fix: icon size again
This commit is contained in:
90
packages/api-extractor-model/src/model/ApiCallSignature.ts
Normal file
90
packages/api-extractor-model/src/model/ApiCallSignature.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin.js';
|
||||
import {
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
ApiTypeParameterListMixin,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiCallSignature}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiCallSignatureOptions
|
||||
extends IApiTypeParameterListMixinOptions,
|
||||
IApiParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript function call signature.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiCallSignature` represents a TypeScript declaration such as `(x: number, y: number): number`
|
||||
* in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export interface IChooser {
|
||||
* // A call signature:
|
||||
* (x: number, y: number): number;
|
||||
*
|
||||
* // Another overload for this call signature:
|
||||
* (x: string, y: string): string;
|
||||
* }
|
||||
*
|
||||
* function chooseFirst<T>(x: T, y: T): T {
|
||||
* return x;
|
||||
* }
|
||||
*
|
||||
* let chooser: IChooser = chooseFirst;
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiCallSignature extends ApiTypeParameterListMixin(
|
||||
ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
public constructor(options: IApiCallSignatureOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(overloadIndex: number): string {
|
||||
return `|${ApiItemKind.CallSignature}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.CallSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiCallSignature.getContainerKey(this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const parent: DeclarationReference = this.parent
|
||||
? this.parent.canonicalReference
|
||||
: // .withMeaning() requires some kind of component
|
||||
DeclarationReference.empty().addNavigationStep(Navigation.Members as any, '(parent)');
|
||||
return parent.withMeaning(Meaning.CallSignature as any).withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
157
packages/api-extractor-model/src/model/ApiClass.ts
Normal file
157
packages/api-extractor-model/src/model/ApiClass.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions, type IApiDeclaredItemJson } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import {
|
||||
ApiAbstractMixin,
|
||||
type IApiAbstractMixinJson,
|
||||
type IApiAbstractMixinOptions,
|
||||
} from '../mixins/ApiAbstractMixin.js';
|
||||
import {
|
||||
type IApiExportedMixinJson,
|
||||
type IApiExportedMixinOptions,
|
||||
ApiExportedMixin,
|
||||
} from '../mixins/ApiExportedMixin.js';
|
||||
import { ApiItemContainerMixin, type IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import {
|
||||
ApiTypeParameterListMixin,
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
type IApiTypeParameterListMixinJson,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
import type { IExcerptTokenRange } from '../mixins/Excerpt.js';
|
||||
import type { DeserializerContext } from './DeserializerContext.js';
|
||||
import { HeritageType } from './HeritageType.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiClass}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiClassOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiAbstractMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiExportedMixinOptions {
|
||||
extendsTokenRange: IExcerptTokenRange | undefined;
|
||||
implementsTokenRanges: IExcerptTokenRange[];
|
||||
}
|
||||
|
||||
export interface IApiClassJson
|
||||
extends IApiDeclaredItemJson,
|
||||
IApiAbstractMixinJson,
|
||||
IApiTypeParameterListMixinJson,
|
||||
IApiExportedMixinJson {
|
||||
extendsTokenRange?: IExcerptTokenRange;
|
||||
implementsTokenRanges: IExcerptTokenRange[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript class declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiClass` represents a TypeScript declaration such as this:
|
||||
*
|
||||
* ```ts
|
||||
* export class X { }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiClass extends ApiItemContainerMixin(
|
||||
ApiNameMixin(ApiAbstractMixin(ApiTypeParameterListMixin(ApiReleaseTagMixin(ApiExportedMixin(ApiDeclaredItem))))),
|
||||
) {
|
||||
/**
|
||||
* The base class that this class inherits from (using the `extends` keyword), or undefined if there is no base class.
|
||||
*/
|
||||
public readonly extendsType: HeritageType | undefined;
|
||||
|
||||
private readonly _implementsTypes: HeritageType[] = [];
|
||||
|
||||
public constructor(options: IApiClassOptions) {
|
||||
super(options);
|
||||
|
||||
if (options.extendsTokenRange) {
|
||||
this.extendsType = new HeritageType(this.buildExcerpt(options.extendsTokenRange));
|
||||
} else {
|
||||
this.extendsType = undefined;
|
||||
}
|
||||
|
||||
for (const implementsTokenRange of options.implementsTokenRanges) {
|
||||
this._implementsTypes.push(new HeritageType(this.buildExcerpt(implementsTokenRange)));
|
||||
}
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.Class}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public static override onDeserializeInto(
|
||||
options: Partial<IApiClassOptions>,
|
||||
context: DeserializerContext,
|
||||
jsonObject: IApiClassJson,
|
||||
): void {
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.extendsTokenRange = jsonObject.extendsTokenRange;
|
||||
options.implementsTokenRanges = jsonObject.implementsTokenRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiClass.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of interfaces that this class implements using the `implements` keyword.
|
||||
*/
|
||||
public get implementsTypes(): readonly HeritageType[] {
|
||||
return this._implementsTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override serializeInto(jsonObject: Partial<IApiClassJson>): void {
|
||||
super.serializeInto(jsonObject);
|
||||
|
||||
// Note that JSON does not support the "undefined" value, so we simply omit the field entirely if it is undefined
|
||||
if (this.extendsType) {
|
||||
jsonObject.extendsTokenRange = this.extendsType.excerpt.tokenRange;
|
||||
}
|
||||
|
||||
jsonObject.implementsTokenRanges = this.implementsTypes.map((x) => x.excerpt.tokenRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Class as any);
|
||||
}
|
||||
}
|
||||
103
packages/api-extractor-model/src/model/ApiConstructSignature.ts
Normal file
103
packages/api-extractor-model/src/model/ApiConstructSignature.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin.js';
|
||||
import {
|
||||
ApiTypeParameterListMixin,
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiConstructor}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiConstructSignatureOptions
|
||||
extends IApiTypeParameterListMixinOptions,
|
||||
IApiParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript construct signature that belongs to an `ApiInterface`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiConstructSignature` represents a construct signature using the `new` keyword such as in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export interface IVector {
|
||||
* x: number;
|
||||
* y: number;
|
||||
* }
|
||||
*
|
||||
* export interface IVectorConstructor {
|
||||
* // A construct signature:
|
||||
* new(x: number, y: number): IVector;
|
||||
* }
|
||||
*
|
||||
* export function createVector(vectorConstructor: IVectorConstructor,
|
||||
* x: number, y: number): IVector {
|
||||
* return new vectorConstructor(x, y);
|
||||
* }
|
||||
*
|
||||
* class Vector implements IVector {
|
||||
* public x: number;
|
||||
* public y: number;
|
||||
* public constructor(x: number, y: number) {
|
||||
* this.x = x;
|
||||
* this.y = y;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* let vector: Vector = createVector(Vector, 1, 2);
|
||||
* ```
|
||||
*
|
||||
* Compare with {@link ApiConstructor}, which describes the class constructor itself.
|
||||
* @public
|
||||
*/
|
||||
export class ApiConstructSignature extends ApiTypeParameterListMixin(
|
||||
ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
public constructor(options: IApiConstructSignatureOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(overloadIndex: number): string {
|
||||
return `|${ApiItemKind.ConstructSignature}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.ConstructSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiConstructSignature.getContainerKey(this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const parent: DeclarationReference = this.parent
|
||||
? this.parent.canonicalReference
|
||||
: // .withMeaning() requires some kind of component
|
||||
DeclarationReference.empty().addNavigationStep(Navigation.Members as any, '(parent)');
|
||||
return parent.withMeaning(Meaning.ConstructSignature as any).withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
81
packages/api-extractor-model/src/model/ApiConstructor.ts
Normal file
81
packages/api-extractor-model/src/model/ApiConstructor.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { ApiProtectedMixin, type IApiProtectedMixinOptions } from '../mixins/ApiProtectedMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiConstructor}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiConstructorOptions
|
||||
extends IApiParameterListMixinOptions,
|
||||
IApiProtectedMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript class constructor declaration that belongs to an `ApiClass`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiConstructor` represents a declaration using the `constructor` keyword such as in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export class Vector {
|
||||
* public x: number;
|
||||
* public y: number;
|
||||
*
|
||||
* // A class constructor:
|
||||
* public constructor(x: number, y: number) {
|
||||
* this.x = x;
|
||||
* this.y = y;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Compare with {@link ApiConstructSignature}, which describes the construct signature for a class constructor.
|
||||
* @public
|
||||
*/
|
||||
export class ApiConstructor extends ApiParameterListMixin(ApiProtectedMixin(ApiReleaseTagMixin(ApiDeclaredItem))) {
|
||||
public constructor(options: IApiConstructorOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(overloadIndex: number): string {
|
||||
return `|${ApiItemKind.Constructor}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Constructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiConstructor.getContainerKey(this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const parent: DeclarationReference = this.parent
|
||||
? this.parent.canonicalReference
|
||||
: // .withMeaning() requires some kind of component
|
||||
DeclarationReference.empty().addNavigationStep(Navigation.Members as any, '(parent)');
|
||||
return parent.withMeaning(Meaning.Constructor as any).withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
89
packages/api-extractor-model/src/model/ApiEntryPoint.ts
Normal file
89
packages/api-extractor-model/src/model/ApiEntryPoint.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiItem, ApiItemKind } from '../items/ApiItem.js';
|
||||
import { ApiItemContainerMixin, type IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiPackage } from './ApiPackage.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiEntryPoint}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IApiNameMixinOptions {}
|
||||
|
||||
/**
|
||||
* Represents the entry point for an NPM package.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiEntryPoint` represents the entry point to an NPM package. API Extractor does not currently support
|
||||
* analysis of multiple entry points, but the `ApiEntryPoint` object is included to support a future feature.
|
||||
* In the current implementation, `ApiEntryPoint.importPath` is always the empty string.
|
||||
*
|
||||
* For example, suppose the package.json file looks like this:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "name": "example-library",
|
||||
* "version": "1.0.0",
|
||||
* "main": "./lib/index.js",
|
||||
* "typings": "./lib/index.d.ts"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In this example, the `ApiEntryPoint` would represent the TypeScript module for `./lib/index.js`.
|
||||
* @public
|
||||
*/
|
||||
export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem)) {
|
||||
public constructor(options: IApiEntryPointOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.EntryPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
// No prefix needed, because ApiEntryPoint is the only possible member of an ApiPackage
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The module path for this entry point, relative to the parent `ApiPackage`. In the current implementation,
|
||||
* this is always the empty string, indicating the default entry point.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* API Extractor does not currently support analysis of multiple entry points. If that feature is implemented
|
||||
* in the future, then the `ApiEntryPoint.importPath` will be used to distinguish different entry points,
|
||||
* for example: `controls/Button` in `import { Button } from "example-package/controls/Button";`.
|
||||
*
|
||||
* The `ApiEntryPoint.name` property stores the same value as `ApiEntryPoint.importPath`.
|
||||
*/
|
||||
public get importPath(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
if (this.parent instanceof ApiPackage) {
|
||||
return DeclarationReference.package(this.parent.name, this.importPath);
|
||||
}
|
||||
|
||||
return DeclarationReference.empty();
|
||||
}
|
||||
}
|
||||
97
packages/api-extractor-model/src/model/ApiEnum.ts
Normal file
97
packages/api-extractor-model/src/model/ApiEnum.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiExportedMixinOptions, ApiExportedMixin } from '../mixins/ApiExportedMixin.js';
|
||||
import { ApiItemContainerMixin, type IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import type { ApiEnumMember } from './ApiEnumMember.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiEnum}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiEnumOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiExportedMixinOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript enum declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiEnum` represents an enum declaration such as `FontSizes` in the example below:
|
||||
*
|
||||
* ```ts
|
||||
* export enum FontSizes {
|
||||
* Small = 100,
|
||||
* Medium = 200,
|
||||
* Large = 300
|
||||
* }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiEnum extends ApiItemContainerMixin(
|
||||
ApiNameMixin(ApiReleaseTagMixin(ApiExportedMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
public constructor(options: IApiEnumOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.Enum}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Enum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get members(): readonly ApiEnumMember[] {
|
||||
return super.members as readonly ApiEnumMember[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiEnum.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override addMember(member: ApiEnumMember): void {
|
||||
if (member.kind !== ApiItemKind.EnumMember) {
|
||||
throw new Error('Only ApiEnumMember objects can be added to an ApiEnum');
|
||||
}
|
||||
|
||||
super.addMember(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Enum as any);
|
||||
}
|
||||
}
|
||||
101
packages/api-extractor-model/src/model/ApiEnumMember.ts
Normal file
101
packages/api-extractor-model/src/model/ApiEnumMember.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { ApiInitializerMixin, type IApiInitializerMixinOptions } from '../mixins/ApiInitializerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiEnumMember}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiEnumMemberOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiInitializerMixinOptions {}
|
||||
|
||||
/**
|
||||
* Options for customizing the sort order of {@link ApiEnum} members.
|
||||
*
|
||||
* @privateRemarks
|
||||
* This enum is currently only used by the `@microsoft/api-extractor` package; it is declared here
|
||||
* because we anticipate that if more options are added in the future, their sorting will be implemented
|
||||
* by the `@microsoft/api-extractor-model` package.
|
||||
*
|
||||
* See https://github.com/microsoft/rushstack/issues/918 for details.
|
||||
* @public
|
||||
*/
|
||||
export enum EnumMemberOrder {
|
||||
/**
|
||||
* `ApiEnumMember` items are sorted according to their {@link ApiItem.getSortKey}. The order is
|
||||
* basically alphabetical by identifier name, but otherwise unspecified to allow for cosmetic improvements.
|
||||
*
|
||||
* This is the default behavior.
|
||||
*/
|
||||
ByName = 'by-name',
|
||||
|
||||
/**
|
||||
* `ApiEnumMember` items preserve the original order of the declarations in the source file.
|
||||
* (This disables the automatic sorting that is normally applied based on {@link ApiItem.getSortKey}.)
|
||||
*/
|
||||
Preserve = 'preserve',
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a member of a TypeScript enum declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiEnumMember` represents an enum member such as `Small = 100` in the example below:
|
||||
*
|
||||
* ```ts
|
||||
* export enum FontSizes {
|
||||
* Small = 100,
|
||||
* Medium = 200,
|
||||
* Large = 300
|
||||
* }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiEnumMember extends ApiNameMixin(ApiReleaseTagMixin(ApiInitializerMixin(ApiDeclaredItem))) {
|
||||
public constructor(options: IApiEnumMemberOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
// No prefix needed, because ApiEnumMember is the only possible member of an ApiEnum
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.EnumMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiEnumMember.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(Navigation.Exports as any, nameComponent)
|
||||
.withMeaning(Meaning.Member as any);
|
||||
}
|
||||
}
|
||||
89
packages/api-extractor-model/src/model/ApiFunction.ts
Normal file
89
packages/api-extractor-model/src/model/ApiFunction.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiExportedMixinOptions, ApiExportedMixin } from '../mixins/ApiExportedMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin.js';
|
||||
import {
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
ApiTypeParameterListMixin,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiFunction}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiFunctionOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiExportedMixinOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript function declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiFunction` represents a TypeScript declaration such as this example:
|
||||
*
|
||||
* ```ts
|
||||
* export function getAverage(x: number, y: number): number {
|
||||
* return (x + y) / 2.0;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Functions are exported by an entry point module or by a namespace. Compare with {@link ApiMethod}, which
|
||||
* represents a function that is a member of a class.
|
||||
* @public
|
||||
*/
|
||||
export class ApiFunction extends ApiNameMixin(
|
||||
ApiTypeParameterListMixin(
|
||||
ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(ApiExportedMixin(ApiDeclaredItem)))),
|
||||
),
|
||||
) {
|
||||
public constructor(options: IApiFunctionOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string, overloadIndex: number): string {
|
||||
return `${name}|${ApiItemKind.Function}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiFunction.getContainerKey(this.name, this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Function as any)
|
||||
.withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
80
packages/api-extractor-model/src/model/ApiIndexSignature.ts
Normal file
80
packages/api-extractor-model/src/model/ApiIndexSignature.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { type IApiReadonlyMixinOptions, ApiReadonlyMixin } from '../mixins/ApiReadonlyMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiIndexSignature}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiIndexSignatureOptions
|
||||
extends IApiParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiReadonlyMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript index signature.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiIndexSignature` represents a TypeScript declaration such as `[x: number]: number` in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export interface INumberTable {
|
||||
* // An index signature
|
||||
* [value: number]: number;
|
||||
*
|
||||
* // An overloaded index signature
|
||||
* [name: string]: number;
|
||||
* }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiIndexSignature extends ApiParameterListMixin(
|
||||
ApiReleaseTagMixin(ApiReturnTypeMixin(ApiReadonlyMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
public constructor(options: IApiIndexSignatureOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(overloadIndex: number): string {
|
||||
return `|${ApiItemKind.IndexSignature}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.IndexSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiIndexSignature.getContainerKey(this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const parent: DeclarationReference = this.parent
|
||||
? this.parent.canonicalReference
|
||||
: // .withMeaning() requires some kind of component
|
||||
DeclarationReference.empty().addNavigationStep(Navigation.Members as any, '(parent)');
|
||||
return parent.withMeaning(Meaning.IndexSignature as any).withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
143
packages/api-extractor-model/src/model/ApiInterface.ts
Normal file
143
packages/api-extractor-model/src/model/ApiInterface.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions, type IApiDeclaredItemJson } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import {
|
||||
type IApiExportedMixinJson,
|
||||
type IApiExportedMixinOptions,
|
||||
ApiExportedMixin,
|
||||
} from '../mixins/ApiExportedMixin.js';
|
||||
import {
|
||||
ApiItemContainerMixin,
|
||||
type IApiItemContainerMixinOptions,
|
||||
type IApiItemContainerJson,
|
||||
} from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin, type IApiNameMixinJson } from '../mixins/ApiNameMixin.js';
|
||||
import {
|
||||
type IApiReleaseTagMixinOptions,
|
||||
ApiReleaseTagMixin,
|
||||
type IApiReleaseTagMixinJson,
|
||||
} from '../mixins/ApiReleaseTagMixin.js';
|
||||
import {
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
type IApiTypeParameterListMixinJson,
|
||||
ApiTypeParameterListMixin,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
import type { IExcerptTokenRange } from '../mixins/Excerpt.js';
|
||||
import type { DeserializerContext } from './DeserializerContext.js';
|
||||
import { HeritageType } from './HeritageType.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiInterface}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiInterfaceOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiExportedMixinOptions {
|
||||
extendsTokenRanges: IExcerptTokenRange[];
|
||||
}
|
||||
|
||||
export interface IApiInterfaceJson
|
||||
extends IApiItemContainerJson,
|
||||
IApiNameMixinJson,
|
||||
IApiTypeParameterListMixinJson,
|
||||
IApiReleaseTagMixinJson,
|
||||
IApiDeclaredItemJson,
|
||||
IApiExportedMixinJson {
|
||||
extendsTokenRanges: IExcerptTokenRange[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript class declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiInterface` represents a TypeScript declaration such as this:
|
||||
*
|
||||
* ```ts
|
||||
* export interface X extends Y {
|
||||
* }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiInterface extends ApiItemContainerMixin(
|
||||
ApiNameMixin(ApiTypeParameterListMixin(ApiReleaseTagMixin(ApiExportedMixin(ApiDeclaredItem)))),
|
||||
) {
|
||||
private readonly _extendsTypes: HeritageType[] = [];
|
||||
|
||||
public constructor(options: IApiInterfaceOptions) {
|
||||
super(options);
|
||||
|
||||
for (const extendsTokenRange of options.extendsTokenRanges) {
|
||||
this._extendsTypes.push(new HeritageType(this.buildExcerpt(extendsTokenRange)));
|
||||
}
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.Interface}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public static override onDeserializeInto(
|
||||
options: Partial<IApiInterfaceOptions>,
|
||||
context: DeserializerContext,
|
||||
jsonObject: IApiInterfaceJson,
|
||||
): void {
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.extendsTokenRanges = jsonObject.extendsTokenRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Interface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiInterface.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of base interfaces that this interface inherits from using the `extends` keyword.
|
||||
*/
|
||||
public get extendsTypes(): readonly HeritageType[] {
|
||||
return this._extendsTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override serializeInto(jsonObject: Partial<IApiInterfaceJson>): void {
|
||||
super.serializeInto(jsonObject);
|
||||
|
||||
jsonObject.extendsTokenRanges = this.extendsTypes.map((x) => x.excerpt.tokenRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Interface as any);
|
||||
}
|
||||
}
|
||||
104
packages/api-extractor-model/src/model/ApiMethod.ts
Normal file
104
packages/api-extractor-model/src/model/ApiMethod.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiAbstractMixinOptions, ApiAbstractMixin } from '../mixins/ApiAbstractMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiOptionalMixin, type IApiOptionalMixinOptions } from '../mixins/ApiOptionalMixin.js';
|
||||
import { type IApiParameterListMixinOptions, ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import { ApiProtectedMixin, type IApiProtectedMixinOptions } from '../mixins/ApiProtectedMixin.js';
|
||||
import { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { ApiReturnTypeMixin, type IApiReturnTypeMixinOptions } from '../mixins/ApiReturnTypeMixin.js';
|
||||
import { ApiStaticMixin, type IApiStaticMixinOptions } from '../mixins/ApiStaticMixin.js';
|
||||
import {
|
||||
ApiTypeParameterListMixin,
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiMethod}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiMethodOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiAbstractMixinOptions,
|
||||
IApiOptionalMixinOptions,
|
||||
IApiParameterListMixinOptions,
|
||||
IApiProtectedMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiStaticMixinOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript member function declaration that belongs to an `ApiClass`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiMethod` represents a TypeScript declaration such as the `render` member function in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export class Widget {
|
||||
* public render(): void { }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Compare with {@link ApiMethodSignature}, which represents a method belonging to an interface.
|
||||
* For example, a class method can be `static` but an interface method cannot.
|
||||
* @public
|
||||
*/
|
||||
export class ApiMethod extends ApiNameMixin(
|
||||
ApiAbstractMixin(
|
||||
ApiOptionalMixin(
|
||||
ApiParameterListMixin(
|
||||
ApiProtectedMixin(
|
||||
ApiReleaseTagMixin(ApiReturnTypeMixin(ApiStaticMixin(ApiTypeParameterListMixin(ApiDeclaredItem)))),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
) {
|
||||
public constructor(options: IApiMethodOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string, isStatic: boolean, overloadIndex: number): string {
|
||||
if (isStatic) {
|
||||
return `${name}|${ApiItemKind.Method}|static|${overloadIndex}`;
|
||||
} else {
|
||||
return `${name}|${ApiItemKind.Method}|instance|${overloadIndex}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiMethod.getContainerKey(this.name, this.isStatic, this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep((this.isStatic ? Navigation.Exports : Navigation.Members) as any, nameComponent)
|
||||
.withMeaning(Meaning.Member as any)
|
||||
.withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
86
packages/api-extractor-model/src/model/ApiMethodSignature.ts
Normal file
86
packages/api-extractor-model/src/model/ApiMethodSignature.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiOptionalMixin, type IApiOptionalMixinOptions } from '../mixins/ApiOptionalMixin.js';
|
||||
import { ApiParameterListMixin, type IApiParameterListMixinOptions } from '../mixins/ApiParameterListMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from '../mixins/ApiReturnTypeMixin.js';
|
||||
import {
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
ApiTypeParameterListMixin,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface IApiMethodSignatureOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiParameterListMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReturnTypeMixinOptions,
|
||||
IApiOptionalMixinOptions,
|
||||
IApiDeclaredItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript member function declaration that belongs to an `ApiInterface`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiMethodSignature` represents a TypeScript declaration such as the `render` member function in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export interface IWidget {
|
||||
* render(): void;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Compare with {@link ApiMethod}, which represents a method belonging to a class.
|
||||
* For example, a class method can be `static` but an interface method cannot.
|
||||
* @public
|
||||
*/
|
||||
export class ApiMethodSignature extends ApiNameMixin(
|
||||
ApiTypeParameterListMixin(
|
||||
ApiParameterListMixin(ApiReleaseTagMixin(ApiReturnTypeMixin(ApiOptionalMixin(ApiDeclaredItem)))),
|
||||
),
|
||||
) {
|
||||
public constructor(options: IApiMethodSignatureOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string, overloadIndex: number): string {
|
||||
return `${name}|${ApiItemKind.MethodSignature}|${overloadIndex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.MethodSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiMethodSignature.getContainerKey(this.name, this.overloadIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(Navigation.Members as any, nameComponent)
|
||||
.withMeaning(Meaning.Member as any)
|
||||
.withOverloadIndex(this.overloadIndex);
|
||||
}
|
||||
}
|
||||
207
packages/api-extractor-model/src/model/ApiModel.ts
Normal file
207
packages/api-extractor-model/src/model/ApiModel.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DocDeclarationReference } from '@microsoft/tsdoc';
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { PackageName } from '@rushstack/node-core-library';
|
||||
import { ApiItem, ApiItemKind } from '../items/ApiItem.js';
|
||||
import { ApiItemContainerMixin } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { ApiPackage } from './ApiPackage.js';
|
||||
import { ModelReferenceResolver, type IResolveDeclarationReferenceResult } from './ModelReferenceResolver.js';
|
||||
|
||||
/**
|
||||
* A serializable representation of a collection of API declarations.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* An `ApiModel` represents a collection of API declarations that can be serialized to disk. It captures all the
|
||||
* important information needed to generate documentation, without any reliance on the TypeScript compiler engine.
|
||||
*
|
||||
* An `ApiModel` acts as the root of a tree of objects that all inherit from the `ApiItem` base class.
|
||||
* The tree children are determined by the {@link (ApiItemContainerMixin:interface)} mixin base class. The model
|
||||
* contains packages. Packages have an entry point (today, only one). And the entry point can contain various types
|
||||
* of API declarations. The container relationships might look like this:
|
||||
*
|
||||
* ```
|
||||
* Things that can contain other things:
|
||||
*
|
||||
* - ApiModel
|
||||
* - ApiPackage
|
||||
* - ApiEntryPoint
|
||||
* - ApiClass
|
||||
* - ApiMethod
|
||||
* - ApiProperty
|
||||
* - ApiEnum
|
||||
* - ApiEnumMember
|
||||
* - ApiInterface
|
||||
* - ApiMethodSignature
|
||||
* - ApiPropertySignature
|
||||
* - ApiNamespace
|
||||
* - (ApiClass, ApiEnum, ApiInterace, ...)
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* Normally, API Extractor writes an .api.json file to disk for each project that it builds. Then, a tool like
|
||||
* API Documenter can load the various `ApiPackage` objects into a single `ApiModel` and process them as a group.
|
||||
* This is useful because compilation generally occurs separately (e.g. because projects may reside in different
|
||||
* Git repos, or because they build with different TypeScript compiler configurations that may be incompatible),
|
||||
* whereas API Documenter cannot detect broken hyperlinks without seeing the entire documentation set.
|
||||
* @public
|
||||
*/
|
||||
export class ApiModel extends ApiItemContainerMixin(ApiItem) {
|
||||
private readonly _resolver: ModelReferenceResolver;
|
||||
|
||||
private _packagesByName: Map<string, ApiPackage> | undefined = undefined;
|
||||
|
||||
private _apiItemsByCanonicalReference: Map<string, ApiItem> | undefined = undefined;
|
||||
|
||||
public constructor() {
|
||||
super({});
|
||||
|
||||
this._resolver = new ModelReferenceResolver(this);
|
||||
}
|
||||
|
||||
public loadPackage(apiJsonFilename: string): ApiPackage {
|
||||
const apiPackage: ApiPackage = ApiPackage.loadFromJsonFile(apiJsonFilename);
|
||||
this.addMember(apiPackage);
|
||||
return apiPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/class-literal-property-style
|
||||
public override get containerKey(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
public get packages(): readonly ApiPackage[] {
|
||||
return this.members as readonly ApiPackage[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override addMember(member: ApiPackage): void {
|
||||
if (member.kind !== ApiItemKind.Package) {
|
||||
throw new Error('Only items of type ApiPackage may be added to an ApiModel');
|
||||
}
|
||||
|
||||
super.addMember(member);
|
||||
this._packagesByName = undefined; // invalidate the cache
|
||||
this._apiItemsByCanonicalReference = undefined; // invalidate the cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Efficiently finds a package by the NPM package name.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* If the NPM scope is omitted in the package name, it will still be found provided that it is an unambiguous match.
|
||||
* For example, it's often convenient to write `{@link node-core-library#JsonFile}` instead of
|
||||
* `{@link @rushstack/node-core-library#JsonFile}`.
|
||||
*/
|
||||
public tryGetPackageByName(packageName: string): ApiPackage | undefined {
|
||||
// Build the lookup on demand
|
||||
if (this._packagesByName === undefined) {
|
||||
this._packagesByName = new Map<string, ApiPackage>();
|
||||
|
||||
const unscopedMap: Map<string, ApiPackage | undefined> = new Map<string, ApiPackage | undefined>();
|
||||
|
||||
for (const apiPackage of this.packages) {
|
||||
if (this._packagesByName.get(apiPackage.name)) {
|
||||
// This should not happen
|
||||
throw new Error(`The model contains multiple packages with the name ${apiPackage.name}`);
|
||||
}
|
||||
|
||||
this._packagesByName.set(apiPackage.name, apiPackage);
|
||||
|
||||
const unscopedName: string = PackageName.parse(apiPackage.name).unscopedName;
|
||||
|
||||
if (unscopedMap.has(unscopedName)) {
|
||||
// If another package has the same unscoped name, then we won't register it
|
||||
unscopedMap.set(unscopedName, undefined);
|
||||
} else {
|
||||
unscopedMap.set(unscopedName, apiPackage);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [unscopedName, apiPackage] of unscopedMap) {
|
||||
if (apiPackage && !this._packagesByName.has(unscopedName)) {
|
||||
// If the unscoped name is unambiguous, then we can also use it as a lookup
|
||||
this._packagesByName.set(unscopedName, apiPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._packagesByName.get(packageName);
|
||||
}
|
||||
|
||||
public resolveDeclarationReference(
|
||||
declarationReference: DeclarationReference | DocDeclarationReference,
|
||||
contextApiItem: ApiItem | undefined,
|
||||
): IResolveDeclarationReferenceResult {
|
||||
if (declarationReference instanceof DocDeclarationReference) {
|
||||
return this._resolver.resolve(declarationReference, contextApiItem);
|
||||
} else if (declarationReference instanceof DeclarationReference) {
|
||||
// use this._apiItemsByCanonicalReference to look up ApiItem
|
||||
|
||||
// Build the lookup on demand
|
||||
if (!this._apiItemsByCanonicalReference) {
|
||||
this._apiItemsByCanonicalReference = new Map<string, ApiItem>();
|
||||
|
||||
for (const apiPackage of this.packages) {
|
||||
this._initApiItemsRecursive(apiPackage, this._apiItemsByCanonicalReference);
|
||||
}
|
||||
}
|
||||
|
||||
const result: IResolveDeclarationReferenceResult = {
|
||||
resolvedApiItem: undefined,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
|
||||
const apiItem: ApiItem | undefined = this._apiItemsByCanonicalReference.get(declarationReference.toString());
|
||||
|
||||
if (apiItem) {
|
||||
result.resolvedApiItem = apiItem;
|
||||
} else {
|
||||
result.errorMessage = `${declarationReference.toString()} can not be located`;
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
// NOTE: The "instanceof DeclarationReference" test assumes a specific version of the @microsoft/tsdoc package.
|
||||
throw new TypeError(
|
||||
'The "declarationReference" parameter must be an instance of' +
|
||||
' DocDeclarationReference or DeclarationReference',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _initApiItemsRecursive(apiItem: ApiItem, apiItemsByCanonicalReference: Map<string, ApiItem>): void {
|
||||
if (apiItem.canonicalReference && !apiItem.canonicalReference.isEmpty) {
|
||||
apiItemsByCanonicalReference.set(apiItem.canonicalReference.toString(), apiItem);
|
||||
}
|
||||
|
||||
// Recurse container members
|
||||
if (ApiItemContainerMixin.isBaseClassOf(apiItem)) {
|
||||
for (const apiMember of apiItem.members) {
|
||||
this._initApiItemsRecursive(apiMember, apiItemsByCanonicalReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
return DeclarationReference.empty();
|
||||
}
|
||||
}
|
||||
80
packages/api-extractor-model/src/model/ApiNamespace.ts
Normal file
80
packages/api-extractor-model/src/model/ApiNamespace.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { type IApiDeclaredItemOptions, ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { type IApiExportedMixinOptions, ApiExportedMixin } from '../mixins/ApiExportedMixin.js';
|
||||
import { ApiItemContainerMixin, type IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiClass}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiNamespaceOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiExportedMixinOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript namespace declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiNamespace` represents a TypeScript declaration such `X` or `Y` in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export namespace X {
|
||||
* export namespace Y {
|
||||
* export interface IWidget {
|
||||
* render(): void;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiNamespace extends ApiItemContainerMixin(
|
||||
ApiNameMixin(ApiReleaseTagMixin(ApiExportedMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
public constructor(options: IApiNamespaceOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.Namespace}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiNamespace.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Namespace as any);
|
||||
}
|
||||
}
|
||||
312
packages/api-extractor-model/src/model/ApiPackage.ts
Normal file
312
packages/api-extractor-model/src/model/ApiPackage.ts
Normal file
@@ -0,0 +1,312 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { TSDocConfiguration } from '@microsoft/tsdoc';
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
|
||||
import {
|
||||
JsonFile,
|
||||
type IJsonFileSaveOptions,
|
||||
PackageJsonLookup,
|
||||
type IPackageJson,
|
||||
type JsonObject,
|
||||
} from '@rushstack/node-core-library';
|
||||
import { ApiDocumentedItem, type IApiDocumentedItemOptions } from '../items/ApiDocumentedItem.js';
|
||||
import { ApiItem, ApiItemKind, type IApiItemJson } from '../items/ApiItem.js';
|
||||
import { ApiItemContainerMixin, type IApiItemContainerMixinOptions } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import type { ApiEntryPoint } from './ApiEntryPoint.js';
|
||||
import { DeserializerContext, ApiJsonSchemaVersion } from './DeserializerContext.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiPackage}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiPackageOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiDocumentedItemOptions {
|
||||
projectFolderUrl?: string | undefined;
|
||||
tsdocConfiguration: TSDocConfiguration;
|
||||
}
|
||||
|
||||
export interface IApiPackageMetadataJson {
|
||||
/**
|
||||
* To support forwards compatibility, the `oldestForwardsCompatibleVersion` field tracks the oldest schema version
|
||||
* whose corresponding deserializer could safely load this file.
|
||||
*
|
||||
* @remarks
|
||||
* Normally api-extractor-model should refuse to load a schema version that is newer than the latest version
|
||||
* that its deserializer understands. However, sometimes a schema change may merely introduce some new fields
|
||||
* without modifying or removing any existing fields. In this case, an older api-extractor-model library can
|
||||
* safely deserialize the newer version (by ignoring the extra fields that it doesn't recognize). The newer
|
||||
* serializer can use this field to communicate that.
|
||||
*
|
||||
* If present, the `oldestForwardsCompatibleVersion` must be less than or equal to
|
||||
* `IApiPackageMetadataJson.schemaVersion`.
|
||||
*/
|
||||
oldestForwardsCompatibleVersion?: ApiJsonSchemaVersion;
|
||||
|
||||
/**
|
||||
* The schema version for the .api.json file format. Used for determining whether the file format is
|
||||
* supported, and for backwards compatibility.
|
||||
*/
|
||||
schemaVersion: ApiJsonSchemaVersion;
|
||||
|
||||
/**
|
||||
* The NPM package name for the tool that wrote the *.api.json file.
|
||||
* For informational purposes only.
|
||||
*/
|
||||
toolPackage: string;
|
||||
|
||||
/**
|
||||
* The NPM package version for the tool that wrote the *.api.json file.
|
||||
* For informational purposes only.
|
||||
*/
|
||||
toolVersion: string;
|
||||
|
||||
/**
|
||||
* The TSDoc configuration that was used when analyzing the API for this package.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* The structure of this objet is defined by the `@microsoft/tsdoc-config` library.
|
||||
* Normally this configuration is loaded from the project's tsdoc.json file. It is stored
|
||||
* in the .api.json file so that doc comments can be parsed accurately when loading the file.
|
||||
*/
|
||||
tsdocConfig: JsonObject;
|
||||
}
|
||||
|
||||
export interface IApiPackageJson extends IApiItemJson {
|
||||
/**
|
||||
* A file header that stores metadata about the tool that wrote the *.api.json file.
|
||||
*/
|
||||
metadata: IApiPackageMetadataJson;
|
||||
|
||||
/**
|
||||
* The base URL where the project's source code can be viewed on a website such as GitHub or
|
||||
* Azure DevOps. This URL path corresponds to the `<projectFolder>` path on disk. Provided via the
|
||||
* `api-extractor.json` config.
|
||||
*/
|
||||
projectFolderUrl?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link ApiPackage.saveToJsonFile}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiPackageSaveOptions extends IJsonFileSaveOptions {
|
||||
/**
|
||||
* Set to true only when invoking API Extractor's test harness.
|
||||
*
|
||||
* @remarks
|
||||
* When `testMode` is true, the `toolVersion` field in the .api.json file is assigned an empty string
|
||||
* to prevent spurious diffs in output files tracked for tests.
|
||||
*/
|
||||
testMode?: boolean;
|
||||
|
||||
/**
|
||||
* Optionally specifies a value for the "toolPackage" field in the output .api.json data file;
|
||||
* otherwise, the value will be "api-extractor-model".
|
||||
*/
|
||||
toolPackage?: string;
|
||||
|
||||
/**
|
||||
* Optionally specifies a value for the "toolVersion" field in the output .api.json data file;
|
||||
* otherwise, the value will be the current version of the api-extractor-model package.
|
||||
*/
|
||||
toolVersion?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an NPM package containing API declarations.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
* @public
|
||||
*/
|
||||
export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumentedItem)) {
|
||||
private readonly _tsdocConfiguration: TSDocConfiguration;
|
||||
|
||||
private readonly _projectFolderUrl?: string | undefined;
|
||||
|
||||
public constructor(options: IApiPackageOptions) {
|
||||
super(options);
|
||||
|
||||
this._tsdocConfiguration = options.tsdocConfiguration;
|
||||
this._projectFolderUrl = options.projectFolderUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public static override onDeserializeInto(
|
||||
options: Partial<IApiPackageOptions>,
|
||||
context: DeserializerContext,
|
||||
jsonObject: IApiPackageJson,
|
||||
): void {
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.projectFolderUrl = jsonObject.projectFolderUrl;
|
||||
}
|
||||
|
||||
public static loadFromJsonFile(apiJsonFilename: string): ApiPackage {
|
||||
const jsonObject: IApiPackageJson = JsonFile.load(apiJsonFilename);
|
||||
|
||||
if (!jsonObject?.metadata || typeof jsonObject.metadata.schemaVersion !== 'number') {
|
||||
throw new Error(
|
||||
`Error loading ${apiJsonFilename}:` +
|
||||
`\nThe file format is not recognized; the "metadata.schemaVersion" field is missing or invalid`,
|
||||
);
|
||||
}
|
||||
|
||||
const schemaVersion: number = jsonObject.metadata.schemaVersion;
|
||||
|
||||
if (schemaVersion < ApiJsonSchemaVersion.OLDEST_SUPPORTED) {
|
||||
throw new Error(
|
||||
`Error loading ${apiJsonFilename}:` +
|
||||
`\nThe file format is version ${schemaVersion},` +
|
||||
` whereas ${ApiJsonSchemaVersion.OLDEST_SUPPORTED} is the oldest version supported by this tool`,
|
||||
);
|
||||
}
|
||||
|
||||
let oldestForwardsCompatibleVersion: number = schemaVersion;
|
||||
if (jsonObject.metadata.oldestForwardsCompatibleVersion) {
|
||||
// Sanity check
|
||||
if (jsonObject.metadata.oldestForwardsCompatibleVersion > schemaVersion) {
|
||||
throw new Error(
|
||||
`Error loading ${apiJsonFilename}:` +
|
||||
`\nInvalid file format; "oldestForwardsCompatibleVersion" cannot be newer than "schemaVersion"`,
|
||||
);
|
||||
}
|
||||
|
||||
oldestForwardsCompatibleVersion = jsonObject.metadata.oldestForwardsCompatibleVersion;
|
||||
}
|
||||
|
||||
let versionToDeserialize: number = schemaVersion;
|
||||
if (versionToDeserialize > ApiJsonSchemaVersion.LATEST) {
|
||||
// If the file format is too new, can we treat it as some earlier compatible version
|
||||
// as indicated by oldestForwardsCompatibleVersion?
|
||||
versionToDeserialize = Math.max(oldestForwardsCompatibleVersion, ApiJsonSchemaVersion.LATEST);
|
||||
|
||||
if (versionToDeserialize > ApiJsonSchemaVersion.LATEST) {
|
||||
// Nope, still too new
|
||||
throw new Error(
|
||||
`Error loading ${apiJsonFilename}:` +
|
||||
`\nThe file format version ${schemaVersion} was written by a newer release of` +
|
||||
` the api-extractor-model library; you may need to upgrade your software`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
|
||||
|
||||
if (versionToDeserialize >= ApiJsonSchemaVersion.V_1004) {
|
||||
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromObject(jsonObject.metadata.tsdocConfig);
|
||||
if (tsdocConfigFile.hasErrors) {
|
||||
throw new Error(`Error loading ${apiJsonFilename}:\n` + tsdocConfigFile.getErrorSummary());
|
||||
}
|
||||
|
||||
tsdocConfigFile.configureParser(tsdocConfiguration);
|
||||
}
|
||||
|
||||
const context: DeserializerContext = new DeserializerContext({
|
||||
apiJsonFilename,
|
||||
toolPackage: jsonObject.metadata.toolPackage,
|
||||
toolVersion: jsonObject.metadata.toolVersion,
|
||||
versionToDeserialize,
|
||||
tsdocConfiguration,
|
||||
});
|
||||
|
||||
return ApiItem.deserialize(jsonObject, context) as ApiPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Package;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
// No prefix needed, because ApiPackage is the only possible member of an ApiModel
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public get entryPoints(): readonly ApiEntryPoint[] {
|
||||
return this.members as readonly ApiEntryPoint[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The TSDoc configuration that was used when analyzing the API for this package.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Normally this configuration is loaded from the project's tsdoc.json file. It is stored
|
||||
* in the .api.json file so that doc comments can be parsed accurately when loading the file.
|
||||
*/
|
||||
public get tsdocConfiguration(): TSDocConfiguration {
|
||||
return this._tsdocConfiguration;
|
||||
}
|
||||
|
||||
public get projectFolderUrl(): string | undefined {
|
||||
return this._projectFolderUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override addMember(member: ApiEntryPoint): void {
|
||||
if (member.kind !== ApiItemKind.EntryPoint) {
|
||||
throw new Error('Only items of type ApiEntryPoint may be added to an ApiPackage');
|
||||
}
|
||||
|
||||
super.addMember(member);
|
||||
}
|
||||
|
||||
public findEntryPointsByPath(importPath: string): readonly ApiEntryPoint[] {
|
||||
return this.findMembersByName(importPath) as readonly ApiEntryPoint[];
|
||||
}
|
||||
|
||||
public saveToJsonFile(apiJsonFilename: string, options?: IApiPackageSaveOptions): void {
|
||||
const ioptions = options ?? {};
|
||||
|
||||
const packageJson: IPackageJson = PackageJsonLookup.loadOwnPackageJson(__dirname);
|
||||
|
||||
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(this.tsdocConfiguration);
|
||||
const tsdocConfig: JsonObject = tsdocConfigFile.saveToObject();
|
||||
|
||||
const jsonObject: IApiPackageJson = {
|
||||
metadata: {
|
||||
toolPackage: ioptions.toolPackage ?? packageJson.name,
|
||||
// In test mode, we don't write the real version, since that would cause spurious diffs whenever
|
||||
// the version is bumped. Instead we write a placeholder string.
|
||||
toolVersion: ioptions.testMode ? '[test mode]' : ioptions.toolVersion ?? packageJson.version,
|
||||
schemaVersion: ApiJsonSchemaVersion.LATEST,
|
||||
oldestForwardsCompatibleVersion: ApiJsonSchemaVersion.OLDEST_FORWARDS_COMPATIBLE,
|
||||
tsdocConfig,
|
||||
},
|
||||
} as IApiPackageJson;
|
||||
|
||||
if (this.projectFolderUrl) {
|
||||
jsonObject.projectFolderUrl = this.projectFolderUrl;
|
||||
}
|
||||
|
||||
this.serializeInto(jsonObject);
|
||||
JsonFile.save(jsonObject, apiJsonFilename, ioptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
return DeclarationReference.package(this.name);
|
||||
}
|
||||
}
|
||||
95
packages/api-extractor-model/src/model/ApiProperty.ts
Normal file
95
packages/api-extractor-model/src/model/ApiProperty.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { ApiPropertyItem, type IApiPropertyItemOptions } from '../items/ApiPropertyItem.js';
|
||||
import { ApiAbstractMixin, type IApiAbstractMixinOptions } from '../mixins/ApiAbstractMixin.js';
|
||||
import { ApiInitializerMixin, type IApiInitializerMixinOptions } from '../mixins/ApiInitializerMixin.js';
|
||||
import { ApiProtectedMixin, type IApiProtectedMixinOptions } from '../mixins/ApiProtectedMixin.js';
|
||||
import { ApiStaticMixin, type IApiStaticMixinOptions } from '../mixins/ApiStaticMixin.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiProperty}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiPropertyOptions
|
||||
extends IApiPropertyItemOptions,
|
||||
IApiAbstractMixinOptions,
|
||||
IApiProtectedMixinOptions,
|
||||
IApiStaticMixinOptions,
|
||||
IApiInitializerMixinOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript property declaration that belongs to an `ApiClass`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiProperty` represents a TypeScript declaration such as the `width` and `height` members in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export class Widget {
|
||||
* public width: number = 100;
|
||||
*
|
||||
* public get height(): number {
|
||||
* if (this.isSquashed()) {
|
||||
* return 0;
|
||||
* } else {
|
||||
* return this.clientArea.height;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Note that member variables are also considered to be properties.
|
||||
*
|
||||
* If the property has both a getter function and setter function, they will be represented by a single `ApiProperty`
|
||||
* and must have a single documentation comment.
|
||||
*
|
||||
* Compare with {@link ApiPropertySignature}, which represents a property belonging to an interface.
|
||||
* For example, a class property can be `static` but an interface property cannot.
|
||||
* @public
|
||||
*/
|
||||
export class ApiProperty extends ApiAbstractMixin(
|
||||
ApiProtectedMixin(ApiStaticMixin(ApiInitializerMixin(ApiPropertyItem))),
|
||||
) {
|
||||
public constructor(options: IApiPropertyOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string, isStatic: boolean): string {
|
||||
if (isStatic) {
|
||||
return `${name}|${ApiItemKind.Property}|static`;
|
||||
} else {
|
||||
return `${name}|${ApiItemKind.Property}|instance`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Property;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiProperty.getContainerKey(this.name, this.isStatic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep((this.isStatic ? Navigation.Exports : Navigation.Members) as any, nameComponent)
|
||||
.withMeaning(Meaning.Member as any);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import { ApiPropertyItem, type IApiPropertyItemOptions } from '../items/ApiPropertyItem.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiPropertySignature}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiPropertySignatureOptions extends IApiPropertyItemOptions {}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript property declaration that belongs to an `ApiInterface`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiPropertySignature` represents a TypeScript declaration such as the `width` and `height` members in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export interface IWidget {
|
||||
* readonly width: number;
|
||||
* height: number;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Compare with {@link ApiProperty}, which represents a property belonging to a class.
|
||||
* For example, a class property can be `static` but an interface property cannot.
|
||||
* @public
|
||||
*/
|
||||
export class ApiPropertySignature extends ApiPropertyItem {
|
||||
public constructor(options: IApiPropertySignatureOptions) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.PropertySignature}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.PropertySignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiPropertySignature.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(Navigation.Members as any, nameComponent)
|
||||
.withMeaning(Meaning.Member as any);
|
||||
}
|
||||
}
|
||||
137
packages/api-extractor-model/src/model/ApiTypeAlias.ts
Normal file
137
packages/api-extractor-model/src/model/ApiTypeAlias.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions, type IApiDeclaredItemJson } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import {
|
||||
type IApiExportedMixinJson,
|
||||
type IApiExportedMixinOptions,
|
||||
ApiExportedMixin,
|
||||
} from '../mixins/ApiExportedMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import {
|
||||
ApiTypeParameterListMixin,
|
||||
type IApiTypeParameterListMixinOptions,
|
||||
type IApiTypeParameterListMixinJson,
|
||||
} from '../mixins/ApiTypeParameterListMixin.js';
|
||||
import type { Excerpt, IExcerptTokenRange } from '../mixins/Excerpt.js';
|
||||
import type { DeserializerContext } from './DeserializerContext.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiTypeAlias}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiTypeAliasOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiTypeParameterListMixinOptions,
|
||||
IApiExportedMixinOptions {
|
||||
typeTokenRange: IExcerptTokenRange;
|
||||
}
|
||||
|
||||
export interface IApiTypeAliasJson extends IApiDeclaredItemJson, IApiTypeParameterListMixinJson, IApiExportedMixinJson {
|
||||
typeTokenRange: IExcerptTokenRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript type alias declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiTypeAlias` represents a definition such as one of these examples:
|
||||
*
|
||||
* ```ts
|
||||
* // A union type:
|
||||
* export type Shape = Square | Triangle | Circle;
|
||||
*
|
||||
* // A generic type alias:
|
||||
* export type BoxedValue<T> = { value: T };
|
||||
*
|
||||
* export type BoxedArray<T> = { array: T[] };
|
||||
*
|
||||
* // A conditional type alias:
|
||||
* export type Boxed<T> = T extends any[] ? BoxedArray<T[number]> : BoxedValue<T>;
|
||||
*
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiTypeAlias extends ApiTypeParameterListMixin(
|
||||
ApiNameMixin(ApiReleaseTagMixin(ApiExportedMixin(ApiDeclaredItem))),
|
||||
) {
|
||||
/**
|
||||
* An {@link Excerpt} that describes the type of the alias.
|
||||
*
|
||||
* @remarks
|
||||
* In the example below, the `typeExcerpt` would correspond to the subexpression
|
||||
* `T extends any[] ? BoxedArray<T[number]> : BoxedValue<T>;`:
|
||||
*
|
||||
* ```ts
|
||||
* export type Boxed<T> = T extends any[] ? BoxedArray<T[number]> : BoxedValue<T>;
|
||||
* ```
|
||||
*/
|
||||
public readonly typeExcerpt: Excerpt;
|
||||
|
||||
public constructor(options: IApiTypeAliasOptions) {
|
||||
super(options);
|
||||
|
||||
this.typeExcerpt = this.buildExcerpt(options.typeTokenRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public static override onDeserializeInto(
|
||||
options: Partial<IApiTypeAliasOptions>,
|
||||
context: DeserializerContext,
|
||||
jsonObject: IApiTypeAliasJson,
|
||||
): void {
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.typeTokenRange = jsonObject.typeTokenRange;
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.TypeAlias}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.TypeAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiTypeAlias.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override serializeInto(jsonObject: Partial<IApiTypeAliasJson>): void {
|
||||
super.serializeInto(jsonObject);
|
||||
|
||||
jsonObject.typeTokenRange = this.typeExcerpt.tokenRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.TypeAlias as any);
|
||||
}
|
||||
}
|
||||
121
packages/api-extractor-model/src/model/ApiVariable.ts
Normal file
121
packages/api-extractor-model/src/model/ApiVariable.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { DeclarationReference, type Component } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { ApiDeclaredItem, type IApiDeclaredItemOptions, type IApiDeclaredItemJson } from '../items/ApiDeclaredItem.js';
|
||||
import { ApiItemKind, Navigation, Meaning } from '../items/ApiItem.js';
|
||||
import {
|
||||
type IApiExportedMixinJson,
|
||||
type IApiExportedMixinOptions,
|
||||
ApiExportedMixin,
|
||||
} from '../mixins/ApiExportedMixin.js';
|
||||
import { ApiInitializerMixin, type IApiInitializerMixinOptions } from '../mixins/ApiInitializerMixin.js';
|
||||
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||
import { ApiReadonlyMixin, type IApiReadonlyMixinOptions } from '../mixins/ApiReadonlyMixin.js';
|
||||
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||
import type { IExcerptTokenRange, Excerpt } from '../mixins/Excerpt.js';
|
||||
import type { DeserializerContext } from './DeserializerContext.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link ApiVariable}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IApiVariableOptions
|
||||
extends IApiNameMixinOptions,
|
||||
IApiReleaseTagMixinOptions,
|
||||
IApiReadonlyMixinOptions,
|
||||
IApiDeclaredItemOptions,
|
||||
IApiInitializerMixinOptions,
|
||||
IApiExportedMixinOptions {
|
||||
variableTypeTokenRange: IExcerptTokenRange;
|
||||
}
|
||||
|
||||
export interface IApiVariableJson extends IApiDeclaredItemJson, IApiExportedMixinJson {
|
||||
variableTypeTokenRange: IExcerptTokenRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a TypeScript variable declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||
* API declarations.
|
||||
*
|
||||
* `ApiVariable` represents an exported `const` or `let` object such as these examples:
|
||||
*
|
||||
* ```ts
|
||||
* // A variable declaration
|
||||
* export let verboseLogging: boolean;
|
||||
*
|
||||
* // A constant variable declaration with an initializer
|
||||
* export const canvas: IWidget = createCanvas();
|
||||
* ```
|
||||
* @public
|
||||
*/
|
||||
export class ApiVariable extends ApiNameMixin(
|
||||
ApiReleaseTagMixin(ApiReadonlyMixin(ApiInitializerMixin(ApiExportedMixin(ApiDeclaredItem)))),
|
||||
) {
|
||||
/**
|
||||
* An {@link Excerpt} that describes the type of the variable.
|
||||
*/
|
||||
public readonly variableTypeExcerpt: Excerpt;
|
||||
|
||||
public constructor(options: IApiVariableOptions) {
|
||||
super(options);
|
||||
|
||||
this.variableTypeExcerpt = this.buildExcerpt(options.variableTypeTokenRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public static override onDeserializeInto(
|
||||
options: Partial<IApiVariableOptions>,
|
||||
context: DeserializerContext,
|
||||
jsonObject: IApiVariableJson,
|
||||
): void {
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.variableTypeTokenRange = jsonObject.variableTypeTokenRange;
|
||||
}
|
||||
|
||||
public static getContainerKey(name: string): string {
|
||||
return `${name}|${ApiItemKind.Variable}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get kind(): ApiItemKind {
|
||||
return ApiItemKind.Variable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override get containerKey(): string {
|
||||
return ApiVariable.getContainerKey(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public override serializeInto(jsonObject: Partial<IApiVariableJson>): void {
|
||||
super.serializeInto(jsonObject);
|
||||
|
||||
jsonObject.variableTypeTokenRange = this.variableTypeExcerpt.tokenRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta @override
|
||||
*/
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
const nameComponent: Component = DeclarationReference.parseComponent(this.name);
|
||||
const navigation: Navigation = this.isExported ? Navigation.Exports : Navigation.Locals;
|
||||
return (this.parent ? this.parent.canonicalReference : DeclarationReference.empty())
|
||||
.addNavigationStep(navigation as any, nameComponent)
|
||||
.withMeaning(Meaning.Variable as any);
|
||||
}
|
||||
}
|
||||
93
packages/api-extractor-model/src/model/Deserializer.ts
Normal file
93
packages/api-extractor-model/src/model/Deserializer.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import type { IApiDeclaredItemJson } from '../items/ApiDeclaredItem.js';
|
||||
import { type IApiItemJson, type IApiItemOptions, type ApiItem, ApiItemKind } from '../items/ApiItem.js';
|
||||
import type { IApiPropertyItemJson } from '../items/ApiPropertyItem.js';
|
||||
import { ApiCallSignature, type IApiCallSignatureOptions } from './ApiCallSignature.js';
|
||||
import { ApiClass, type IApiClassOptions, type IApiClassJson } from './ApiClass.js';
|
||||
import { ApiConstructSignature, type IApiConstructSignatureOptions } from './ApiConstructSignature.js';
|
||||
import { ApiConstructor, type IApiConstructorOptions } from './ApiConstructor.js';
|
||||
import { ApiEntryPoint, type IApiEntryPointOptions } from './ApiEntryPoint.js';
|
||||
import { ApiEnum, type IApiEnumOptions } from './ApiEnum.js';
|
||||
import { ApiEnumMember, type IApiEnumMemberOptions } from './ApiEnumMember.js';
|
||||
import { ApiFunction, type IApiFunctionOptions } from './ApiFunction.js';
|
||||
import { ApiIndexSignature, type IApiIndexSignatureOptions } from './ApiIndexSignature.js';
|
||||
import { ApiInterface, type IApiInterfaceOptions, type IApiInterfaceJson } from './ApiInterface.js';
|
||||
import { ApiMethod, type IApiMethodOptions } from './ApiMethod.js';
|
||||
import { ApiMethodSignature, type IApiMethodSignatureOptions } from './ApiMethodSignature.js';
|
||||
import { ApiModel } from './ApiModel.js';
|
||||
import { ApiNamespace, type IApiNamespaceOptions } from './ApiNamespace.js';
|
||||
import { ApiPackage, type IApiPackageOptions, type IApiPackageJson } from './ApiPackage.js';
|
||||
import { ApiProperty, type IApiPropertyOptions } from './ApiProperty.js';
|
||||
import { ApiPropertySignature, type IApiPropertySignatureOptions } from './ApiPropertySignature.js';
|
||||
import { ApiTypeAlias, type IApiTypeAliasOptions, type IApiTypeAliasJson } from './ApiTypeAlias.js';
|
||||
import { ApiVariable, type IApiVariableOptions, type IApiVariableJson } from './ApiVariable.js';
|
||||
import type { DeserializerContext } from './DeserializerContext.js';
|
||||
|
||||
export class Deserializer {
|
||||
public static deserialize(context: DeserializerContext, jsonObject: IApiItemJson): ApiItem {
|
||||
const options: Partial<IApiItemOptions> = {};
|
||||
|
||||
switch (jsonObject.kind) {
|
||||
case ApiItemKind.Class:
|
||||
ApiClass.onDeserializeInto(options, context, jsonObject as IApiClassJson);
|
||||
return new ApiClass(options as IApiClassOptions);
|
||||
case ApiItemKind.CallSignature:
|
||||
ApiCallSignature.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiCallSignature(options as IApiCallSignatureOptions);
|
||||
case ApiItemKind.Constructor:
|
||||
ApiConstructor.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiConstructor(options as IApiConstructorOptions);
|
||||
case ApiItemKind.ConstructSignature:
|
||||
ApiConstructSignature.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiConstructSignature(options as IApiConstructSignatureOptions);
|
||||
case ApiItemKind.EntryPoint:
|
||||
ApiEntryPoint.onDeserializeInto(options, context, jsonObject);
|
||||
return new ApiEntryPoint(options as IApiEntryPointOptions);
|
||||
case ApiItemKind.Enum:
|
||||
ApiEnum.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiEnum(options as IApiEnumOptions);
|
||||
case ApiItemKind.EnumMember:
|
||||
ApiEnumMember.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiEnumMember(options as IApiEnumMemberOptions);
|
||||
case ApiItemKind.Function:
|
||||
ApiFunction.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiFunction(options as IApiFunctionOptions);
|
||||
case ApiItemKind.IndexSignature:
|
||||
ApiIndexSignature.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiIndexSignature(options as IApiIndexSignatureOptions);
|
||||
case ApiItemKind.Interface:
|
||||
ApiInterface.onDeserializeInto(options, context, jsonObject as IApiInterfaceJson);
|
||||
return new ApiInterface(options as IApiInterfaceOptions);
|
||||
case ApiItemKind.Method:
|
||||
ApiMethod.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiMethod(options as IApiMethodOptions);
|
||||
case ApiItemKind.MethodSignature:
|
||||
ApiMethodSignature.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiMethodSignature(options as IApiMethodSignatureOptions);
|
||||
case ApiItemKind.Model:
|
||||
return new ApiModel();
|
||||
case ApiItemKind.Namespace:
|
||||
ApiNamespace.onDeserializeInto(options, context, jsonObject as IApiDeclaredItemJson);
|
||||
return new ApiNamespace(options as IApiNamespaceOptions);
|
||||
case ApiItemKind.Package:
|
||||
ApiPackage.onDeserializeInto(options, context, jsonObject as IApiPackageJson);
|
||||
return new ApiPackage(options as IApiPackageOptions);
|
||||
case ApiItemKind.Property:
|
||||
ApiProperty.onDeserializeInto(options, context, jsonObject as IApiPropertyItemJson);
|
||||
return new ApiProperty(options as IApiPropertyOptions);
|
||||
case ApiItemKind.PropertySignature:
|
||||
ApiPropertySignature.onDeserializeInto(options, context, jsonObject as IApiPropertyItemJson);
|
||||
return new ApiPropertySignature(options as IApiPropertySignatureOptions);
|
||||
case ApiItemKind.TypeAlias:
|
||||
ApiTypeAlias.onDeserializeInto(options, context, jsonObject as IApiTypeAliasJson);
|
||||
return new ApiTypeAlias(options as IApiTypeAliasOptions);
|
||||
case ApiItemKind.Variable:
|
||||
ApiVariable.onDeserializeInto(options, context, jsonObject as IApiVariableJson);
|
||||
return new ApiVariable(options as IApiVariableOptions);
|
||||
default:
|
||||
throw new Error(`Failed to deserialize unsupported API item type ${JSON.stringify(jsonObject.kind)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
packages/api-extractor-model/src/model/DeserializerContext.ts
Normal file
153
packages/api-extractor-model/src/model/DeserializerContext.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import type { TSDocConfiguration } from '@microsoft/tsdoc';
|
||||
|
||||
export enum ApiJsonSchemaVersion {
|
||||
/**
|
||||
* The initial release.
|
||||
*/
|
||||
V_1000 = 1_000,
|
||||
|
||||
/**
|
||||
* Add support for type parameters and type alias types.
|
||||
*/
|
||||
V_1001 = 1_001,
|
||||
|
||||
/**
|
||||
* Remove `canonicalReference` field. This field was for diagnostic purposes only and was never deserialized.
|
||||
*/
|
||||
V_1002 = 1_002,
|
||||
|
||||
/**
|
||||
* Reintroduce the `canonicalReference` field using the experimental new TSDoc declaration reference notation.
|
||||
*
|
||||
* This is not a breaking change because this field is never deserialized; it is provided for informational
|
||||
* purposes only.
|
||||
*/
|
||||
V_1003 = 1_003,
|
||||
|
||||
/**
|
||||
* Add a `tsdocConfig` field that tracks the TSDoc configuration for parsing doc comments.
|
||||
*
|
||||
* This is not a breaking change because an older implementation will still work correctly. The
|
||||
* custom tags will be skipped over by the parser.
|
||||
*/
|
||||
V_1004 = 1_004,
|
||||
|
||||
/**
|
||||
* Add an `isOptional` field to `Parameter` and `TypeParameter` to track whether a function parameter is optional.
|
||||
*
|
||||
* When loading older JSON files, the value defaults to `false`.
|
||||
*/
|
||||
V_1005 = 1_005,
|
||||
|
||||
/**
|
||||
* Add an `isProtected` field to `ApiConstructor`, `ApiMethod`, and `ApiProperty` to
|
||||
* track whether a class member has the `protected` modifier.
|
||||
*
|
||||
* Add an `isReadonly` field to `ApiProperty`, `ApiPropertySignature`, and `ApiVariable` to
|
||||
* track whether the item is readonly.
|
||||
*
|
||||
* When loading older JSON files, the values default to `false`.
|
||||
*/
|
||||
V_1006 = 1_006,
|
||||
|
||||
/**
|
||||
* Add `ApiItemContainerMixin.preserveMemberOrder` to support enums that preserve their original sort order.
|
||||
*
|
||||
* When loading older JSON files, the value default to `false`.
|
||||
*/
|
||||
V_1007 = 1_007,
|
||||
|
||||
/**
|
||||
* Add an `initializerTokenRange` field to `ApiProperty` and `ApiVariable` to track the item's
|
||||
* initializer.
|
||||
*
|
||||
* When loading older JSON files, this range is empty.
|
||||
*/
|
||||
V_1008 = 1_008,
|
||||
|
||||
/**
|
||||
* Add an `isReadonly` field to `ApiIndexSignature` to track whether the item is readonly.
|
||||
*
|
||||
* When loading older JSON files, the values defaults to `false`.
|
||||
*/
|
||||
V_1009 = 1_009,
|
||||
|
||||
/**
|
||||
* Add a `fileUrlPath` field to `ApiDeclaredItem` to track the URL to a declared item's source file.
|
||||
*
|
||||
* When loading older JSON files, the value defaults to `undefined`.
|
||||
*/
|
||||
V_1010 = 1_010,
|
||||
|
||||
/**
|
||||
* Add an `isAbstract` field to `ApiClass`, `ApiMethod`, and `ApiProperty` to
|
||||
* track whether the item is abstract.
|
||||
*
|
||||
* When loading older JSON files, the value defaults to `false`.
|
||||
*/
|
||||
V_1011 = 1_011,
|
||||
|
||||
/**
|
||||
* The current latest .api.json schema version.
|
||||
*
|
||||
* IMPORTANT: When incrementing this number, consider whether `OLDEST_SUPPORTED` or `OLDEST_FORWARDS_COMPATIBLE`
|
||||
* should be updated.
|
||||
*/
|
||||
LATEST = V_1011,
|
||||
|
||||
/**
|
||||
* The oldest .api.json schema version that is still supported for backwards compatibility.
|
||||
*
|
||||
* This must be updated if you change to the file format and do not implement compatibility logic for
|
||||
* deserializing the older representation.
|
||||
*/
|
||||
OLDEST_SUPPORTED = V_1001,
|
||||
|
||||
/**
|
||||
* Used to assign `IApiPackageMetadataJson.oldestForwardsCompatibleVersion`.
|
||||
*
|
||||
* This value must be \<= `ApiJsonSchemaVersion.LATEST`. It must be reset to the `LATEST` value
|
||||
* if the older library would not be able to deserialize your new file format. Adding a nonessential field
|
||||
* is generally okay. Removing, modifying, or reinterpreting existing fields is NOT safe.
|
||||
*/
|
||||
OLDEST_FORWARDS_COMPATIBLE = V_1001,
|
||||
}
|
||||
|
||||
export class DeserializerContext {
|
||||
/**
|
||||
* The path of the file being deserialized, which may be useful for diagnostic purposes.
|
||||
*/
|
||||
public readonly apiJsonFilename: string;
|
||||
|
||||
/**
|
||||
* Metadata from `IApiPackageMetadataJson.toolPackage`.
|
||||
*/
|
||||
public readonly toolPackage: string;
|
||||
|
||||
/**
|
||||
* Metadata from `IApiPackageMetadataJson.toolVersion`.
|
||||
*/
|
||||
public readonly toolVersion: string;
|
||||
|
||||
/**
|
||||
* The version of the schema being deserialized, as obtained from `IApiPackageMetadataJson.schemaVersion`.
|
||||
*/
|
||||
public readonly versionToDeserialize: ApiJsonSchemaVersion;
|
||||
|
||||
/**
|
||||
* The TSDoc configuration for the context.
|
||||
*/
|
||||
public readonly tsdocConfiguration: TSDocConfiguration;
|
||||
|
||||
public constructor(options: DeserializerContext) {
|
||||
this.apiJsonFilename = options.apiJsonFilename;
|
||||
this.toolPackage = options.toolPackage;
|
||||
this.toolVersion = options.toolVersion;
|
||||
this.versionToDeserialize = options.versionToDeserialize;
|
||||
this.tsdocConfiguration = options.tsdocConfiguration;
|
||||
}
|
||||
}
|
||||
44
packages/api-extractor-model/src/model/HeritageType.ts
Normal file
44
packages/api-extractor-model/src/model/HeritageType.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import type { Excerpt } from '../mixins/Excerpt.js';
|
||||
|
||||
/**
|
||||
* Represents a type referenced via an "extends" or "implements" heritage clause for a TypeScript class
|
||||
* or interface.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* For example, consider this declaration:
|
||||
*
|
||||
* ```ts
|
||||
* export class Widget extends Controls.WidgetBase implements Controls.IWidget, IDisposable {
|
||||
* // . . .
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The heritage types are `Controls.WidgetBase`, `Controls.IWidget`, and `IDisposable`.
|
||||
* @public
|
||||
*/
|
||||
export class HeritageType {
|
||||
/**
|
||||
* An excerpt corresponding to the referenced type.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* For example, consider this declaration:
|
||||
*
|
||||
* ```ts
|
||||
* export class Widget extends Controls.WidgetBase implements Controls.IWidget, IDisposable {
|
||||
* // . . .
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The excerpt might be `Controls.WidgetBase`, `Controls.IWidget`, or `IDisposable`.
|
||||
*/
|
||||
public readonly excerpt: Excerpt;
|
||||
|
||||
public constructor(excerpt: Excerpt) {
|
||||
this.excerpt = excerpt;
|
||||
}
|
||||
}
|
||||
235
packages/api-extractor-model/src/model/ModelReferenceResolver.ts
Normal file
235
packages/api-extractor-model/src/model/ModelReferenceResolver.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { type DocDeclarationReference, type DocMemberSelector, SelectorKind } from '@microsoft/tsdoc';
|
||||
import { type ApiItem, ApiItemKind } from '../items/ApiItem.js';
|
||||
import { ApiItemContainerMixin } from '../mixins/ApiItemContainerMixin.js';
|
||||
import { ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import type { ApiEntryPoint } from './ApiEntryPoint.js';
|
||||
import type { ApiModel } from './ApiModel.js';
|
||||
import type { ApiPackage } from './ApiPackage.js';
|
||||
|
||||
/**
|
||||
* Result object for {@link ApiModel.resolveDeclarationReference}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IResolveDeclarationReferenceResult {
|
||||
/**
|
||||
* If resolvedApiItem is undefined, then this will always contain an error message explaining why the
|
||||
* resolution failed.
|
||||
*/
|
||||
errorMessage: string | undefined;
|
||||
|
||||
/**
|
||||
* The referenced ApiItem, if the declaration reference could be resolved.
|
||||
*/
|
||||
resolvedApiItem: ApiItem | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* This resolves a TSDoc declaration reference by walking the `ApiModel` hierarchy.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This class is analogous to `AstReferenceResolver` from the `@microsoft/api-extractor` project,
|
||||
* which resolves declaration references by walking the compiler state.
|
||||
*/
|
||||
export class ModelReferenceResolver {
|
||||
private readonly _apiModel: ApiModel;
|
||||
|
||||
public constructor(apiModel: ApiModel) {
|
||||
this._apiModel = apiModel;
|
||||
}
|
||||
|
||||
public resolve(
|
||||
declarationReference: DocDeclarationReference,
|
||||
contextApiItem: ApiItem | undefined,
|
||||
): IResolveDeclarationReferenceResult {
|
||||
const result: IResolveDeclarationReferenceResult = {
|
||||
resolvedApiItem: undefined,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
|
||||
let apiPackage: ApiPackage | undefined;
|
||||
|
||||
// Is this an absolute reference?
|
||||
if (declarationReference.packageName === undefined) {
|
||||
// If the package name is omitted, try to infer it from the context
|
||||
if (contextApiItem !== undefined) {
|
||||
apiPackage = contextApiItem.getAssociatedPackage();
|
||||
}
|
||||
|
||||
if (apiPackage === undefined) {
|
||||
result.errorMessage = `The reference does not include a package name, and the package could not be inferred from the context`;
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
apiPackage = this._apiModel.tryGetPackageByName(declarationReference.packageName);
|
||||
if (apiPackage === undefined) {
|
||||
result.errorMessage = `The package "${declarationReference.packageName}" could not be located`;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const importPath: string = declarationReference.importPath ?? '';
|
||||
|
||||
const foundEntryPoints: readonly ApiEntryPoint[] = apiPackage.findEntryPointsByPath(importPath);
|
||||
if (foundEntryPoints.length < 1) {
|
||||
result.errorMessage = `The import path "${importPath}" could not be resolved`;
|
||||
return result;
|
||||
}
|
||||
|
||||
let currentItem: ApiItem = foundEntryPoints[0]!;
|
||||
|
||||
// Now search for the member reference
|
||||
for (const memberReference of declarationReference.memberReferences) {
|
||||
if (memberReference.memberSymbol !== undefined) {
|
||||
result.errorMessage = `Symbols are not yet supported in declaration references`;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (memberReference.memberIdentifier === undefined) {
|
||||
result.errorMessage = `Missing member identifier`;
|
||||
return result;
|
||||
}
|
||||
|
||||
const identifier: string = memberReference.memberIdentifier.identifier;
|
||||
|
||||
if (!ApiItemContainerMixin.isBaseClassOf(currentItem)) {
|
||||
// For example, {@link MyClass.myMethod.X} is invalid because methods cannot contain members
|
||||
result.errorMessage = `Unable to resolve ${JSON.stringify(
|
||||
identifier,
|
||||
)} because ${currentItem.getScopedNameWithinPackage()} cannot act as a container`;
|
||||
return result;
|
||||
}
|
||||
|
||||
const foundMembers: readonly ApiItem[] = currentItem.findMembersByName(identifier);
|
||||
if (foundMembers.length === 0) {
|
||||
result.errorMessage = `The member reference ${JSON.stringify(identifier)} was not found`;
|
||||
return result;
|
||||
}
|
||||
|
||||
const memberSelector: DocMemberSelector | undefined = memberReference.selector;
|
||||
if (memberSelector === undefined) {
|
||||
if (foundMembers.length > 1) {
|
||||
result.errorMessage = `The member reference ${JSON.stringify(identifier)} was ambiguous`;
|
||||
return result;
|
||||
}
|
||||
|
||||
currentItem = foundMembers[0]!;
|
||||
} else {
|
||||
let memberSelectorResult: IResolveDeclarationReferenceResult;
|
||||
switch (memberSelector.selectorKind) {
|
||||
case SelectorKind.System:
|
||||
memberSelectorResult = this._selectUsingSystemSelector(foundMembers, memberSelector, identifier);
|
||||
break;
|
||||
case SelectorKind.Index:
|
||||
memberSelectorResult = this._selectUsingIndexSelector(foundMembers, memberSelector, identifier);
|
||||
break;
|
||||
default:
|
||||
result.errorMessage = `The selector "${memberSelector.selector}" is not a supported selector type`;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (memberSelectorResult.resolvedApiItem === undefined) {
|
||||
return memberSelectorResult;
|
||||
}
|
||||
|
||||
currentItem = memberSelectorResult.resolvedApiItem;
|
||||
}
|
||||
}
|
||||
|
||||
result.resolvedApiItem = currentItem;
|
||||
return result;
|
||||
}
|
||||
|
||||
private _selectUsingSystemSelector(
|
||||
foundMembers: readonly ApiItem[],
|
||||
memberSelector: DocMemberSelector,
|
||||
identifier: string,
|
||||
): IResolveDeclarationReferenceResult {
|
||||
const result: IResolveDeclarationReferenceResult = {
|
||||
resolvedApiItem: undefined,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
|
||||
const selectorName: string = memberSelector.selector;
|
||||
|
||||
let selectorItemKind: ApiItemKind;
|
||||
switch (selectorName) {
|
||||
case 'class':
|
||||
selectorItemKind = ApiItemKind.Class;
|
||||
break;
|
||||
case 'enum':
|
||||
selectorItemKind = ApiItemKind.Enum;
|
||||
break;
|
||||
case 'function':
|
||||
selectorItemKind = ApiItemKind.Function;
|
||||
break;
|
||||
case 'interface':
|
||||
selectorItemKind = ApiItemKind.Interface;
|
||||
break;
|
||||
case 'namespace':
|
||||
selectorItemKind = ApiItemKind.Namespace;
|
||||
break;
|
||||
case 'type':
|
||||
selectorItemKind = ApiItemKind.TypeAlias;
|
||||
break;
|
||||
case 'variable':
|
||||
selectorItemKind = ApiItemKind.Variable;
|
||||
break;
|
||||
default:
|
||||
result.errorMessage = `Unsupported system selector "${selectorName}"`;
|
||||
return result;
|
||||
}
|
||||
|
||||
const matches: ApiItem[] = foundMembers.filter((x) => x.kind === selectorItemKind);
|
||||
if (matches.length === 0) {
|
||||
result.errorMessage = `A declaration for "${identifier}" was not found that matches the TSDoc selector "${selectorName}"`;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (matches.length > 1) {
|
||||
result.errorMessage = `More than one declaration "${identifier}" matches the TSDoc selector "${selectorName}"`;
|
||||
}
|
||||
|
||||
result.resolvedApiItem = matches[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
private _selectUsingIndexSelector(
|
||||
foundMembers: readonly ApiItem[],
|
||||
memberSelector: DocMemberSelector,
|
||||
identifier: string,
|
||||
): IResolveDeclarationReferenceResult {
|
||||
const result: IResolveDeclarationReferenceResult = {
|
||||
resolvedApiItem: undefined,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
|
||||
const selectedMembers: ApiItem[] = [];
|
||||
|
||||
const selectorOverloadIndex: number = Number.parseInt(memberSelector.selector, 10);
|
||||
for (const foundMember of foundMembers) {
|
||||
if (ApiParameterListMixin.isBaseClassOf(foundMember) && foundMember.overloadIndex === selectorOverloadIndex) {
|
||||
selectedMembers.push(foundMember);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMembers.length === 0) {
|
||||
result.errorMessage =
|
||||
`An overload for ${JSON.stringify(identifier)} was not found that matches` +
|
||||
` the TSDoc selector ":${selectorOverloadIndex}"`;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (selectedMembers.length === 1) {
|
||||
result.resolvedApiItem = selectedMembers[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
result.errorMessage = `The member reference ${JSON.stringify(identifier)} was ambiguous`;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
79
packages/api-extractor-model/src/model/Parameter.ts
Normal file
79
packages/api-extractor-model/src/model/Parameter.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import type * as tsdoc from '@microsoft/tsdoc';
|
||||
import { ApiDocumentedItem } from '../items/ApiDocumentedItem.js';
|
||||
import type { ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||
import type { Excerpt } from '../mixins/Excerpt.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link Parameter}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IParameterOptions {
|
||||
isOptional: boolean;
|
||||
isRest: boolean;
|
||||
name: string;
|
||||
parameterTypeExcerpt: Excerpt;
|
||||
parent: ApiParameterListMixin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a named parameter for a function-like declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* `Parameter` represents a TypeScript declaration such as `x: number` in this example:
|
||||
*
|
||||
* ```ts
|
||||
* export function add(x: number, y: number): number {
|
||||
* return x + y;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* `Parameter` objects belong to the {@link (ApiParameterListMixin:interface).parameters} collection.
|
||||
* @public
|
||||
*/
|
||||
export class Parameter {
|
||||
/**
|
||||
* An {@link Excerpt} that describes the type of the parameter.
|
||||
*/
|
||||
public readonly parameterTypeExcerpt: Excerpt;
|
||||
|
||||
/**
|
||||
* The parameter name.
|
||||
*/
|
||||
public name: string;
|
||||
|
||||
/**
|
||||
* Whether the parameter is optional.
|
||||
*/
|
||||
public isOptional: boolean;
|
||||
|
||||
/**
|
||||
* Whether the parameter is a rest parameter
|
||||
*/
|
||||
public isRest: boolean;
|
||||
|
||||
private readonly _parent: ApiParameterListMixin;
|
||||
|
||||
public constructor(options: IParameterOptions) {
|
||||
this.name = options.name;
|
||||
this.parameterTypeExcerpt = options.parameterTypeExcerpt;
|
||||
this.isOptional = options.isOptional;
|
||||
this.isRest = options.isRest;
|
||||
this._parent = options.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `@param` documentation for this parameter, if present.
|
||||
*/
|
||||
public get tsdocParamBlock(): tsdoc.DocParamBlock | undefined {
|
||||
if (this._parent instanceof ApiDocumentedItem && this._parent.tsdocComment) {
|
||||
return this._parent.tsdocComment.params.tryGetBlockByName(this.name);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
91
packages/api-extractor-model/src/model/SourceLocation.ts
Normal file
91
packages/api-extractor-model/src/model/SourceLocation.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { URL } from 'node:url';
|
||||
|
||||
/**
|
||||
* Constructor options for `SourceLocation`.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ISourceLocationOptions {
|
||||
/**
|
||||
* The file URL path relative to the `projectFolder` and `projectFolderURL` fields as
|
||||
* defined in the `api-extractor.json` config.
|
||||
*/
|
||||
fileUrlPath?: string | undefined;
|
||||
|
||||
/**
|
||||
* The project folder URL as defined by the `api-extractor.json` config `projectFolderUrl`
|
||||
* setting.
|
||||
*/
|
||||
projectFolderUrl?: string | undefined;
|
||||
|
||||
/**
|
||||
* The column number in the source file. The first column number is 1.
|
||||
*/
|
||||
sourceFileColumn?: number | undefined;
|
||||
|
||||
/**
|
||||
* The line number in the source file. The first line number is 1.
|
||||
*/
|
||||
sourceFileLine?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source location where a given API item is declared.
|
||||
*
|
||||
* @remarks
|
||||
* The source location points to the `.ts` source file where the API item was originally
|
||||
* declared. However, in some cases, if source map resolution fails, it falls back to pointing
|
||||
* to the `.d.ts` file instead.
|
||||
* @public
|
||||
*/
|
||||
export class SourceLocation {
|
||||
private readonly _projectFolderUrl?: string | undefined;
|
||||
|
||||
private readonly _fileUrlPath?: string | undefined;
|
||||
|
||||
private readonly _fileLine?: number | undefined;
|
||||
|
||||
private readonly _fileColumn?: number | undefined;
|
||||
|
||||
public constructor(options: ISourceLocationOptions) {
|
||||
this._projectFolderUrl = options.projectFolderUrl;
|
||||
this._fileUrlPath = options.fileUrlPath;
|
||||
this._fileLine = options.sourceFileLine;
|
||||
this._fileColumn = options.sourceFileColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file URL to the given source location. Returns `undefined` if the file URL
|
||||
* cannot be determined.
|
||||
*/
|
||||
public get fileUrl(): string | undefined {
|
||||
if (this._projectFolderUrl === undefined || this._fileUrlPath === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let projectFolderUrl: string = this._projectFolderUrl;
|
||||
if (!projectFolderUrl.endsWith('/')) {
|
||||
projectFolderUrl += '/';
|
||||
}
|
||||
|
||||
const url: URL = new URL(this._fileUrlPath, projectFolderUrl);
|
||||
return url.href;
|
||||
}
|
||||
|
||||
/**
|
||||
* The line in the `fileUrlPath` where the API item is declared.
|
||||
*/
|
||||
public get fileLine(): number | undefined {
|
||||
return this._fileLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column in the `fileUrlPath` where the API item is declared.
|
||||
*/
|
||||
public get fileColumn(): number | undefined {
|
||||
return this._fileColumn;
|
||||
}
|
||||
}
|
||||
106
packages/api-extractor-model/src/model/TypeParameter.ts
Normal file
106
packages/api-extractor-model/src/model/TypeParameter.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import type * as tsdoc from '@microsoft/tsdoc';
|
||||
import { ApiDocumentedItem } from '../items/ApiDocumentedItem.js';
|
||||
import type { ApiTypeParameterListMixin } from '../mixins/ApiTypeParameterListMixin.js';
|
||||
import type { Excerpt } from '../mixins/Excerpt.js';
|
||||
|
||||
/**
|
||||
* Constructor options for {@link TypeParameter}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ITypeParameterOptions {
|
||||
constraintExcerpt: Excerpt;
|
||||
defaultTypeExcerpt: Excerpt;
|
||||
isOptional: boolean;
|
||||
name: string;
|
||||
parent: ApiTypeParameterListMixin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a named type parameter for a generic declaration.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* `TypeParameter` represents a TypeScript declaration such as `T` in this example:
|
||||
*
|
||||
* ```ts
|
||||
* interface IIdentifier {
|
||||
* getCode(): string;
|
||||
* }
|
||||
*
|
||||
* class BarCode implements IIdentifier {
|
||||
* private _value: number;
|
||||
* public getCode(): string { return this._value.toString(); }
|
||||
* }
|
||||
*
|
||||
* class Book<TIdentifier extends IIdentifier = BarCode> {
|
||||
* public identifier: TIdentifier;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* `TypeParameter` objects belong to the {@link (ApiTypeParameterListMixin:interface).typeParameters} collection.
|
||||
* @public
|
||||
*/
|
||||
export class TypeParameter {
|
||||
/**
|
||||
* An {@link Excerpt} that describes the base constraint of the type parameter.
|
||||
*
|
||||
* @remarks
|
||||
* In the example below, the `constraintExcerpt` would correspond to the `IIdentifier` subexpression:
|
||||
*
|
||||
* ```ts
|
||||
* class Book<TIdentifier extends IIdentifier = BarCode> {
|
||||
* public identifier: TIdentifier;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public readonly constraintExcerpt: Excerpt;
|
||||
|
||||
/**
|
||||
* An {@link Excerpt} that describes the default type of the type parameter.
|
||||
*
|
||||
* @remarks
|
||||
* In the example below, the `defaultTypeExcerpt` would correspond to the `BarCode` subexpression:
|
||||
*
|
||||
* ```ts
|
||||
* class Book<TIdentifier extends IIdentifier = BarCode> {
|
||||
* public identifier: TIdentifier;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public readonly defaultTypeExcerpt: Excerpt;
|
||||
|
||||
/**
|
||||
* The parameter name.
|
||||
*/
|
||||
public name: string;
|
||||
|
||||
/**
|
||||
* Whether the type parameter is optional. True IFF there exists a `defaultTypeExcerpt`.
|
||||
*/
|
||||
public isOptional: boolean;
|
||||
|
||||
private readonly _parent: ApiTypeParameterListMixin;
|
||||
|
||||
public constructor(options: ITypeParameterOptions) {
|
||||
this.name = options.name;
|
||||
this.constraintExcerpt = options.constraintExcerpt;
|
||||
this.defaultTypeExcerpt = options.defaultTypeExcerpt;
|
||||
this.isOptional = options.isOptional;
|
||||
this._parent = options.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `@typeParam` documentation for this parameter, if present.
|
||||
*/
|
||||
public get tsdocTypeParamBlock(): tsdoc.DocParamBlock | undefined {
|
||||
if (this._parent instanceof ApiDocumentedItem && this._parent.tsdocComment) {
|
||||
return this._parent.tsdocComment.typeParams.tryGetBlockByName(this.name);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user