mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +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:
6
.github/labeler.yml
vendored
6
.github/labeler.yml
vendored
@@ -4,6 +4,12 @@ apps:guide:
|
|||||||
apps:website:
|
apps:website:
|
||||||
- apps/website/*
|
- apps/website/*
|
||||||
- apps/website/**/*
|
- apps/website/**/*
|
||||||
|
packages:api-extractor:
|
||||||
|
- packages/api-extractor/*
|
||||||
|
- packages/api-extractor/**/*
|
||||||
|
packages:api-extractor-model:
|
||||||
|
- packages/api-extractor-model/*
|
||||||
|
- packages/api-extractor-model/**/*
|
||||||
packages:brokers:
|
packages:brokers:
|
||||||
- packages/brokers/*
|
- packages/brokers/*
|
||||||
- packages/brokers/**/*
|
- packages/brokers/**/*
|
||||||
|
|||||||
4
.github/labels.yml
vendored
4
.github/labels.yml
vendored
@@ -52,6 +52,10 @@
|
|||||||
color: e4e669
|
color: e4e669
|
||||||
- name: need repro
|
- name: need repro
|
||||||
color: c66037
|
color: c66037
|
||||||
|
- name: packages:api-extractor
|
||||||
|
color: fbca04
|
||||||
|
- name: packages:api-extractor-model
|
||||||
|
color: fbca04
|
||||||
- name: packages:brokers
|
- name: packages:brokers
|
||||||
color: fbca04
|
color: fbca04
|
||||||
- name: packages:builders
|
- name: packages:builders
|
||||||
|
|||||||
1
.npmrc
1
.npmrc
@@ -3,5 +3,4 @@ resolution-mode=highest
|
|||||||
public-hoist-pattern[]=*eslint*
|
public-hoist-pattern[]=*eslint*
|
||||||
public-hoist-pattern[]=*prettier*
|
public-hoist-pattern[]=*prettier*
|
||||||
public-hoist-pattern[]=*@rushstack/node-core-library*
|
public-hoist-pattern[]=*@rushstack/node-core-library*
|
||||||
public-hoist-pattern[]=*@microsoft/api-extractor-model*
|
|
||||||
public-hoist-pattern[]=*jju*
|
public-hoist-pattern[]=*jju*
|
||||||
|
|||||||
@@ -222,7 +222,7 @@
|
|||||||
/**
|
/**
|
||||||
* (REQUIRED) Whether to generate the .d.ts rollup file.
|
* (REQUIRED) Whether to generate the .d.ts rollup file.
|
||||||
*/
|
*/
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
|
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default withBundleAnalyzer({
|
|||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
experimental: {
|
experimental: {
|
||||||
typedRoutes: true,
|
typedRoutes: true,
|
||||||
serverComponentsExternalPackages: ['@rushstack/node-core-library', '@microsoft/api-extractor-model', 'jju'],
|
serverComponentsExternalPackages: ['@rushstack/node-core-library', '@discordjs/api-extractor-model', 'jju'],
|
||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
dangerouslyAllowSVG: true,
|
dangerouslyAllowSVG: true,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
"@discordjs/api-extractor-utils": "workspace:^",
|
"@discordjs/api-extractor-utils": "workspace:^",
|
||||||
"@discordjs/scripts": "workspace:^",
|
"@discordjs/scripts": "workspace:^",
|
||||||
"@discordjs/ui": "workspace:^",
|
"@discordjs/ui": "workspace:^",
|
||||||
"@microsoft/api-extractor-model": "^7.28.2",
|
"@discordjs/api-extractor-model": "workspace:^",
|
||||||
"@microsoft/tsdoc": "^0.14.2",
|
"@microsoft/tsdoc": "^0.14.2",
|
||||||
"@microsoft/tsdoc-config": "0.16.2",
|
"@microsoft/tsdoc-config": "0.16.2",
|
||||||
"@planetscale/database": "^1.11.0",
|
"@planetscale/database": "^1.11.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable react/no-unknown-property */
|
/* eslint-disable react/no-unknown-property */
|
||||||
|
|
||||||
import type { ApiItemKind } from '@microsoft/api-extractor-model';
|
import type { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { ImageResponse } from '@vercel/og';
|
import { ImageResponse } from '@vercel/og';
|
||||||
import type { NextRequest } from 'next/server';
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { tryResolveSummaryText } from '@discordjs/scripts';
|
|
||||||
import type {
|
import type {
|
||||||
ApiClass,
|
ApiClass,
|
||||||
ApiDeclaredItem,
|
ApiDeclaredItem,
|
||||||
@@ -13,8 +12,9 @@ import type {
|
|||||||
ApiTypeAlias,
|
ApiTypeAlias,
|
||||||
ApiVariable,
|
ApiVariable,
|
||||||
ApiFunction,
|
ApiFunction,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import { ApiItemKind, ApiModel } from '@microsoft/api-extractor-model';
|
import { ApiItemKind, ApiModel } from '@discordjs/api-extractor-model';
|
||||||
|
import { tryResolveSummaryText } from '@discordjs/scripts';
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import { fetchModelJSON } from '~/app/docAPI';
|
import { fetchModelJSON } from '~/app/docAPI';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiFunction, ApiItem } from '@microsoft/api-extractor-model';
|
import type { ApiFunction, ApiItem } from '@discordjs/api-extractor-model';
|
||||||
import { ApiModel } from '@microsoft/api-extractor-model';
|
import { ApiModel } from '@discordjs/api-extractor-model';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiDocumentedItem } from '@microsoft/api-extractor-model';
|
import type { ApiDocumentedItem } from '@discordjs/api-extractor-model';
|
||||||
import { ApiAbstractMixin, ApiProtectedMixin, ApiReadonlyMixin, ApiStaticMixin } from '@microsoft/api-extractor-model';
|
import { ApiAbstractMixin, ApiProtectedMixin, ApiReadonlyMixin, ApiStaticMixin } from '@discordjs/api-extractor-model';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
export enum BadgeColor {
|
export enum BadgeColor {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { ApiItemKind } from '@microsoft/api-extractor-model';
|
import type { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
|
import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
|
||||||
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
||||||
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { Anchor } from './Anchor';
|
import { Anchor } from './Anchor';
|
||||||
|
import { SourceLink } from './documentation/SourceLink';
|
||||||
|
|
||||||
export interface CodeListingProps {
|
export interface CodeListingProps {
|
||||||
/**
|
/**
|
||||||
@@ -14,15 +15,26 @@ export interface CodeListingProps {
|
|||||||
* The href of this heading.
|
* The href of this heading.
|
||||||
*/
|
*/
|
||||||
readonly href?: string | undefined;
|
readonly href?: string | undefined;
|
||||||
|
/**
|
||||||
|
* The line in the source code where this part is declared
|
||||||
|
*/
|
||||||
|
readonly sourceLine?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The URL of the source code of this code part
|
||||||
|
*/
|
||||||
|
readonly sourceURL?: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CodeHeading({ href, className, children }: CodeListingProps) {
|
export function CodeHeading({ href, className, children, sourceURL, sourceLine }: CodeListingProps) {
|
||||||
return (
|
return (
|
||||||
|
<div className="flex flex-row place-items-center justify-between gap-1">
|
||||||
<div
|
<div
|
||||||
className={`flex flex-row flex-wrap place-items-center gap-1 break-all font-mono text-lg font-bold ${className}`}
|
className={`flex flex-row flex-wrap place-items-center gap-1 break-all font-mono text-lg font-bold ${className}`}
|
||||||
>
|
>
|
||||||
{href ? <Anchor href={href} /> : null}
|
{href ? <Anchor href={href} /> : null}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
{sourceURL ? <SourceLink className="text-2xl" sourceLine={sourceLine} sourceURL={sourceURL} /> : null}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiModel, Excerpt } from '@microsoft/api-extractor-model';
|
import type { ApiModel, Excerpt } from '@discordjs/api-extractor-model';
|
||||||
import { ExcerptTokenKind } from '@microsoft/api-extractor-model';
|
import { ExcerptTokenKind } from '@discordjs/api-extractor-model';
|
||||||
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
|
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
|
||||||
import { ItemLink } from './ItemLink';
|
import { ItemLink } from './ItemLink';
|
||||||
import { resolveItemURI } from './documentation/util';
|
import { resolveItemURI } from './documentation/util';
|
||||||
@@ -60,7 +60,7 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return token.text;
|
return token.text.replace(/import\("discord-api-types(?:\/v\d+)?"\)\./, '');
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
import type { ApiDeclaredItem } from '@discordjs/api-extractor-model';
|
||||||
import { ItemLink } from './ItemLink';
|
import { ItemLink } from './ItemLink';
|
||||||
import { resolveItemURI } from './documentation/util';
|
import { resolveItemURI } from './documentation/util';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDocumentedItem, ApiParameterListMixin } from '@microsoft/api-extractor-model';
|
import type { ApiDocumentedItem, ApiParameterListMixin } from '@discordjs/api-extractor-model';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { resolveParameters } from '~/util/model';
|
import { resolveParameters } from '~/util/model';
|
||||||
import { ExcerptText } from './ExcerptText';
|
import { ExcerptText } from './ExcerptText';
|
||||||
@@ -16,7 +16,7 @@ export function ParameterTable({ item }: { readonly item: ApiDocumentedItem & Ap
|
|||||||
const rows = useMemo(
|
const rows = useMemo(
|
||||||
() =>
|
() =>
|
||||||
params.map((param) => ({
|
params.map((param) => ({
|
||||||
Name: param.name,
|
Name: param.isRest ? `...${param.name}` : param.name,
|
||||||
Type: <ExcerptText excerpt={param.parameterTypeExcerpt} model={item.getAssociatedModel()!} />,
|
Type: <ExcerptText excerpt={param.parameterTypeExcerpt} model={item.getAssociatedModel()!} />,
|
||||||
Optional: param.isOptional ? 'Yes' : 'No',
|
Optional: param.isOptional ? 'Yes' : 'No',
|
||||||
Description: param.description ? <TSDoc item={item} tsdoc={param.description} /> : 'None',
|
Description: param.description ? <TSDoc item={item} tsdoc={param.description} /> : 'None',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type {
|
|||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
ApiProperty,
|
ApiProperty,
|
||||||
ApiPropertySignature,
|
ApiPropertySignature,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import { Badges } from './Badges';
|
import { Badges } from './Badges';
|
||||||
import { CodeHeading } from './CodeHeading';
|
import { CodeHeading } from './CodeHeading';
|
||||||
@@ -25,7 +25,11 @@ export function Property({
|
|||||||
<div className="flex flex-col scroll-mt-30 gap-4" id={item.displayName}>
|
<div className="flex flex-col scroll-mt-30 gap-4" id={item.displayName}>
|
||||||
<div className="flex flex-col gap-2 md:-ml-9">
|
<div className="flex flex-col gap-2 md:-ml-9">
|
||||||
<Badges item={item} />
|
<Badges item={item} />
|
||||||
<CodeHeading href={`#${item.displayName}`}>
|
<CodeHeading
|
||||||
|
href={`#${item.displayName}`}
|
||||||
|
sourceURL={item.sourceLocation.fileUrl}
|
||||||
|
sourceLine={item.sourceLocation.fileLine}
|
||||||
|
>
|
||||||
{`${item.displayName}${item.isOptional ? '?' : ''}`}
|
{`${item.displayName}${item.isOptional ? '?' : ''}`}
|
||||||
<span>:</span>
|
<span>:</span>
|
||||||
{item.propertyTypeExcerpt.text ? (
|
{item.propertyTypeExcerpt.text ? (
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import type {
|
|||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
ApiProperty,
|
ApiProperty,
|
||||||
ApiPropertySignature,
|
ApiPropertySignature,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { Fragment, useMemo } from 'react';
|
import { Fragment, useMemo } from 'react';
|
||||||
import { resolveMembers } from '~/util/members';
|
import { resolveMembers } from '~/util/members';
|
||||||
import { Property } from './Property';
|
import { Property } from './Property';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { ApiItemKind } from '@microsoft/api-extractor-model';
|
import type { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
||||||
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
||||||
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiModel, Excerpt } from '@microsoft/api-extractor-model';
|
import type { ApiModel, Excerpt } from '@discordjs/api-extractor-model';
|
||||||
import { ExcerptText } from './ExcerptText';
|
import { ExcerptText } from './ExcerptText';
|
||||||
|
|
||||||
export function SignatureText({ excerpt, model }: { readonly excerpt: Excerpt; readonly model: ApiModel }) {
|
export function SignatureText({ excerpt, model }: { readonly excerpt: Excerpt; readonly model: ApiModel }) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiTypeParameterListMixin } from '@microsoft/api-extractor-model';
|
import type { ApiTypeParameterListMixin } from '@discordjs/api-extractor-model';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { ExcerptText } from './ExcerptText';
|
import { ExcerptText } from './ExcerptText';
|
||||||
import { Table } from './Table';
|
import { Table } from './Table';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { VscFileCode } from '@react-icons/all-files/vsc/VscFileCode';
|
|
||||||
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
||||||
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
||||||
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
||||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||||
import { VscSymbolVariable } from '@react-icons/all-files/vsc/VscSymbolVariable';
|
import { VscSymbolVariable } from '@react-icons/all-files/vsc/VscSymbolVariable';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
|
import { SourceLink } from './SourceLink';
|
||||||
|
|
||||||
function generateIcon(kind: ApiItemKind) {
|
function generateIcon(kind: ApiItemKind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
@@ -30,7 +30,13 @@ export function Header({
|
|||||||
kind,
|
kind,
|
||||||
name,
|
name,
|
||||||
sourceURL,
|
sourceURL,
|
||||||
}: PropsWithChildren<{ readonly kind: ApiItemKind; readonly name: string; readonly sourceURL?: string | undefined }>) {
|
sourceLine,
|
||||||
|
}: PropsWithChildren<{
|
||||||
|
readonly kind: ApiItemKind;
|
||||||
|
readonly name: string;
|
||||||
|
readonly sourceLine?: number | undefined;
|
||||||
|
readonly sourceURL?: string | undefined;
|
||||||
|
}>) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h2 className="flex flex-row place-items-center justify-between gap-2 break-all text-2xl font-bold">
|
<h2 className="flex flex-row place-items-center justify-between gap-2 break-all text-2xl font-bold">
|
||||||
@@ -38,11 +44,7 @@ export function Header({
|
|||||||
<span>{generateIcon(kind)}</span>
|
<span>{generateIcon(kind)}</span>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
{sourceURL ? (
|
{sourceURL ? <SourceLink sourceLine={sourceLine} sourceURL={sourceURL} /> : null}
|
||||||
<a className="text-blurple" href={sourceURL} rel="external noopener noreferrer" target="_blank">
|
|
||||||
<VscFileCode />
|
|
||||||
</a>
|
|
||||||
) : null}
|
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiClass, ApiInterface, Excerpt } from '@microsoft/api-extractor-model';
|
import type { ApiClass, ApiInterface, Excerpt } from '@discordjs/api-extractor-model';
|
||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { ExcerptText } from '../ExcerptText';
|
import { ExcerptText } from '../ExcerptText';
|
||||||
|
|
||||||
export function HierarchyText({
|
export function HierarchyText({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDeclaredItem, ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
import type { ApiDeclaredItem, ApiItemContainerMixin } from '@discordjs/api-extractor-model';
|
||||||
import { MethodsSection } from './section/MethodsSection';
|
import { MethodsSection } from './section/MethodsSection';
|
||||||
import { PropertiesSection } from './section/PropertiesSection';
|
import { PropertiesSection } from './section/PropertiesSection';
|
||||||
import { hasProperties, hasMethods } from './util';
|
import { hasProperties, hasMethods } from './util';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
import type { ApiDeclaredItem } from '@discordjs/api-extractor-model';
|
||||||
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
import { SummarySection } from './section/SummarySection';
|
import { SummarySection } from './section/SummarySection';
|
||||||
@@ -10,7 +10,12 @@ export interface ObjectHeaderProps {
|
|||||||
export function ObjectHeader({ item }: ObjectHeaderProps) {
|
export function ObjectHeader({ item }: ObjectHeaderProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header kind={item.kind} name={item.displayName} sourceURL={item.sourceLocation.fileUrl} />
|
<Header
|
||||||
|
kind={item.kind}
|
||||||
|
name={item.displayName}
|
||||||
|
sourceURL={item.sourceLocation.fileUrl}
|
||||||
|
sourceLine={item.sourceLocation.fileLine}
|
||||||
|
/>
|
||||||
{/* @ts-expect-error async component */}
|
{/* @ts-expect-error async component */}
|
||||||
<SyntaxHighlighter code={item.excerpt.text} />
|
<SyntaxHighlighter code={item.excerpt.text} />
|
||||||
<SummarySection item={item} />
|
<SummarySection item={item} />
|
||||||
|
|||||||
22
apps/website/src/components/documentation/SourceLink.tsx
Normal file
22
apps/website/src/components/documentation/SourceLink.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { VscFileCode } from '@react-icons/all-files/vsc/VscFileCode';
|
||||||
|
|
||||||
|
export function SourceLink({
|
||||||
|
className,
|
||||||
|
sourceURL,
|
||||||
|
sourceLine,
|
||||||
|
}: {
|
||||||
|
readonly className?: string | undefined;
|
||||||
|
readonly sourceLine?: number | undefined;
|
||||||
|
readonly sourceURL?: string | undefined;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className={` text-blurple ${className}`}
|
||||||
|
href={sourceLine ? `${sourceURL}#L${sourceLine}` : sourceURL}
|
||||||
|
rel="external noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<VscFileCode />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiConstructor } from '@microsoft/api-extractor-model';
|
import type { ApiConstructor } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||||
import { CodeHeading } from '~/components/CodeHeading';
|
import { CodeHeading } from '~/components/CodeHeading';
|
||||||
import { ParameterTable } from '../../ParameterTable';
|
import { ParameterTable } from '../../ParameterTable';
|
||||||
@@ -10,7 +10,10 @@ export function ConstructorSection({ item }: { readonly item: ApiConstructor })
|
|||||||
return (
|
return (
|
||||||
<DocumentationSection icon={<VscSymbolMethod size={20} />} padded title="Constructor">
|
<DocumentationSection icon={<VscSymbolMethod size={20} />} padded title="Constructor">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<CodeHeading>{`constructor(${parametersString(item)})`}</CodeHeading>
|
<CodeHeading
|
||||||
|
sourceURL={item.sourceLocation.fileUrl}
|
||||||
|
sourceLine={item.sourceLocation.fileLine}
|
||||||
|
>{`constructor(${parametersString(item)})`}</CodeHeading>
|
||||||
{item.tsdocComment ? <TSDoc item={item} tsdoc={item.tsdocComment} /> : null}
|
{item.tsdocComment ? <TSDoc item={item} tsdoc={item.tsdocComment} /> : null}
|
||||||
<ParameterTable item={item} />
|
<ParameterTable item={item} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import type {
|
|||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
ApiMethod,
|
ApiMethod,
|
||||||
ApiMethodSignature,
|
ApiMethodSignature,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||||
import { useMemo, Fragment } from 'react';
|
import { useMemo, Fragment } from 'react';
|
||||||
import { resolveMembers } from '~/util/members';
|
import { resolveMembers } from '~/util/members';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDocumentedItem, ApiParameterListMixin } from '@microsoft/api-extractor-model';
|
import type { ApiDocumentedItem, ApiParameterListMixin } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
||||||
import { ParameterTable } from '../../ParameterTable';
|
import { ParameterTable } from '../../ParameterTable';
|
||||||
import { DocumentationSection } from './DocumentationSection';
|
import { DocumentationSection } from './DocumentationSection';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
import type { ApiItemContainerMixin } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty';
|
import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty';
|
||||||
import { PropertyList } from '../../PropertyList';
|
import { PropertyList } from '../../PropertyList';
|
||||||
import { DocumentationSection } from './DocumentationSection';
|
import { DocumentationSection } from './DocumentationSection';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
import type { ApiDeclaredItem } from '@discordjs/api-extractor-model';
|
||||||
import { VscListSelection } from '@react-icons/all-files/vsc/VscListSelection';
|
import { VscListSelection } from '@react-icons/all-files/vsc/VscListSelection';
|
||||||
import { TSDoc } from '../tsdoc/TSDoc';
|
import { TSDoc } from '../tsdoc/TSDoc';
|
||||||
import { DocumentationSection } from './DocumentationSection';
|
import { DocumentationSection } from './DocumentationSection';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiTypeParameterListMixin } from '@microsoft/api-extractor-model';
|
import type { ApiTypeParameterListMixin } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
||||||
import { TypeParamTable } from '../../TypeParamTable';
|
import { TypeParamTable } from '../../TypeParamTable';
|
||||||
import { DocumentationSection } from './DocumentationSection';
|
import { DocumentationSection } from './DocumentationSection';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiItem } from '@microsoft/api-extractor-model';
|
import type { ApiItem } from '@discordjs/api-extractor-model';
|
||||||
import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
|
import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
|
||||||
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
|
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
|
||||||
import type { Route } from 'next';
|
import type { Route } from 'next';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
import type {
|
import type {
|
||||||
ApiItem,
|
ApiItem,
|
||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
@@ -8,7 +8,7 @@ import type {
|
|||||||
ApiPropertySignature,
|
ApiPropertySignature,
|
||||||
ApiDocumentedItem,
|
ApiDocumentedItem,
|
||||||
ApiParameterListMixin,
|
ApiParameterListMixin,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import { METHOD_SEPARATOR, OVERLOAD_SEPARATOR } from '~/util/constants';
|
import { METHOD_SEPARATOR, OVERLOAD_SEPARATOR } from '~/util/constants';
|
||||||
import { resolveMembers } from '~/util/members';
|
import { resolveMembers } from '~/util/members';
|
||||||
import { resolveParameters } from '~/util/model';
|
import { resolveParameters } from '~/util/model';
|
||||||
@@ -63,9 +63,9 @@ export function serializeMembers(clazz: ApiItemContainerMixin): TableOfContentsS
|
|||||||
export function parametersString(item: ApiDocumentedItem & ApiParameterListMixin) {
|
export function parametersString(item: ApiDocumentedItem & ApiParameterListMixin) {
|
||||||
return resolveParameters(item).reduce((prev, cur, index) => {
|
return resolveParameters(item).reduce((prev, cur, index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return `${prev}${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
return `${prev}${cur.isRest ? '...' : ''}${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${prev}, ${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
return `${prev}, ${cur.isRest ? '...' : ''}${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
||||||
}, '');
|
}, '');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiClass, ApiConstructor } from '@microsoft/api-extractor-model';
|
import type { ApiClass, ApiConstructor } from '@discordjs/api-extractor-model';
|
||||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||||
// import { Outline } from '../Outline';
|
// import { Outline } from '../Outline';
|
||||||
import { Badges } from '../Badges';
|
import { Badges } from '../Badges';
|
||||||
import { Documentation } from '../documentation/Documentation';
|
import { Documentation } from '../documentation/Documentation';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiInterface } from '@microsoft/api-extractor-model';
|
import type { ApiInterface } from '@discordjs/api-extractor-model';
|
||||||
// import { Outline } from '../Outline';
|
// import { Outline } from '../Outline';
|
||||||
import { Documentation } from '../documentation/Documentation';
|
import { Documentation } from '../documentation/Documentation';
|
||||||
import { HierarchyText } from '../documentation/HierarchyText';
|
import { HierarchyText } from '../documentation/HierarchyText';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiTypeAlias } from '@microsoft/api-extractor-model';
|
import type { ApiTypeAlias } from '@discordjs/api-extractor-model';
|
||||||
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
||||||
import { Documentation } from '../documentation/Documentation';
|
import { Documentation } from '../documentation/Documentation';
|
||||||
import { Header } from '../documentation/Header';
|
import { Header } from '../documentation/Header';
|
||||||
@@ -7,7 +7,12 @@ import { SummarySection } from '../documentation/section/SummarySection';
|
|||||||
export function TypeAlias({ item }: { readonly item: ApiTypeAlias }) {
|
export function TypeAlias({ item }: { readonly item: ApiTypeAlias }) {
|
||||||
return (
|
return (
|
||||||
<Documentation>
|
<Documentation>
|
||||||
<Header kind={item.kind} name={item.displayName} sourceURL={item.sourceLocation.fileUrl} />
|
<Header
|
||||||
|
kind={item.kind}
|
||||||
|
name={item.displayName}
|
||||||
|
sourceURL={item.sourceLocation.fileUrl}
|
||||||
|
sourceLine={item.sourceLocation.fileLine}
|
||||||
|
/>
|
||||||
{/* @ts-expect-error async component */}
|
{/* @ts-expect-error async component */}
|
||||||
<SyntaxHighlighter code={item.excerpt.text} />
|
<SyntaxHighlighter code={item.excerpt.text} />
|
||||||
<SummarySection item={item} />
|
<SummarySection item={item} />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiVariable } from '@microsoft/api-extractor-model';
|
import type { ApiVariable } from '@discordjs/api-extractor-model';
|
||||||
import { Documentation } from '../documentation/Documentation';
|
import { Documentation } from '../documentation/Documentation';
|
||||||
import { ObjectHeader } from '../documentation/ObjectHeader';
|
import { ObjectHeader } from '../documentation/ObjectHeader';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiEnum } from '@microsoft/api-extractor-model';
|
import type { ApiEnum } from '@discordjs/api-extractor-model';
|
||||||
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
||||||
import { Panel } from '../../Panel';
|
import { Panel } from '../../Panel';
|
||||||
import { Documentation } from '../../documentation/Documentation';
|
import { Documentation } from '../../documentation/Documentation';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiEnumMember } from '@microsoft/api-extractor-model';
|
import type { ApiEnumMember } from '@discordjs/api-extractor-model';
|
||||||
import { CodeHeading } from '~/components/CodeHeading';
|
import { CodeHeading } from '~/components/CodeHeading';
|
||||||
import { SignatureText } from '../../SignatureText';
|
import { SignatureText } from '../../SignatureText';
|
||||||
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
|
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
|
||||||
@@ -6,7 +6,12 @@ import { TSDoc } from '../../documentation/tsdoc/TSDoc';
|
|||||||
export function EnumMember({ member }: { readonly member: ApiEnumMember }) {
|
export function EnumMember({ member }: { readonly member: ApiEnumMember }) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col scroll-mt-30" id={member.displayName}>
|
<div className="flex flex-col scroll-mt-30" id={member.displayName}>
|
||||||
<CodeHeading className="md:-ml-8.5" href={`#${member.displayName}`}>
|
<CodeHeading
|
||||||
|
className="md:-ml-8.5"
|
||||||
|
href={`#${member.displayName}`}
|
||||||
|
sourceURL={member.sourceLocation.fileUrl}
|
||||||
|
sourceLine={member.sourceLocation.fileLine}
|
||||||
|
>
|
||||||
{member.name}
|
{member.name}
|
||||||
<span>=</span>
|
<span>=</span>
|
||||||
{member.initializerExcerpt ? (
|
{member.initializerExcerpt ? (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiFunction } from '@microsoft/api-extractor-model';
|
import type { ApiFunction } from '@discordjs/api-extractor-model';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Header } from '../../documentation/Header';
|
import { Header } from '../../documentation/Header';
|
||||||
import { FunctionBody } from './FunctionBody';
|
import { FunctionBody } from './FunctionBody';
|
||||||
@@ -6,7 +6,14 @@ import { FunctionBody } from './FunctionBody';
|
|||||||
const OverloadSwitcher = dynamic(async () => import('../../OverloadSwitcher'));
|
const OverloadSwitcher = dynamic(async () => import('../../OverloadSwitcher'));
|
||||||
|
|
||||||
export function Function({ item }: { readonly item: ApiFunction }) {
|
export function Function({ item }: { readonly item: ApiFunction }) {
|
||||||
const header = <Header kind={item.kind} name={item.name} sourceURL={item.sourceLocation.fileUrl} />;
|
const header = (
|
||||||
|
<Header
|
||||||
|
kind={item.kind}
|
||||||
|
name={item.name}
|
||||||
|
sourceURL={item.sourceLocation.fileUrl}
|
||||||
|
sourceLine={item.sourceLocation.fileLine}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
if (item.getMergedSiblings().length > 1) {
|
if (item.getMergedSiblings().length > 1) {
|
||||||
const overloads = item
|
const overloads = item
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiFunction } from '@microsoft/api-extractor-model';
|
import type { ApiFunction } from '@discordjs/api-extractor-model';
|
||||||
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
|
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
|
||||||
import { Documentation } from '../../documentation/Documentation';
|
import { Documentation } from '../../documentation/Documentation';
|
||||||
import { ParameterSection } from '../../documentation/section/ParametersSection';
|
import { ParameterSection } from '../../documentation/section/ParametersSection';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type {
|
|||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
ApiMethod,
|
ApiMethod,
|
||||||
ApiMethodSignature,
|
ApiMethodSignature,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import { MethodDocumentation } from './MethodDocumentation';
|
import { MethodDocumentation } from './MethodDocumentation';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type {
|
|||||||
ApiItemContainerMixin,
|
ApiItemContainerMixin,
|
||||||
ApiMethod,
|
ApiMethod,
|
||||||
ApiMethodSignature,
|
ApiMethodSignature,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import { InheritanceText } from '../../InheritanceText';
|
import { InheritanceText } from '../../InheritanceText';
|
||||||
import { ParameterTable } from '../../ParameterTable';
|
import { ParameterTable } from '../../ParameterTable';
|
||||||
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
|
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiMethod, ApiMethodSignature } from '@microsoft/api-extractor-model';
|
import type { ApiMethod, ApiMethodSignature } from '@discordjs/api-extractor-model';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Badges } from '~/components/Badges';
|
import { Badges } from '~/components/Badges';
|
||||||
import { CodeHeading } from '~/components/CodeHeading';
|
import { CodeHeading } from '~/components/CodeHeading';
|
||||||
@@ -15,7 +15,11 @@ export function MethodHeader({ method }: { readonly method: ApiMethod | ApiMetho
|
|||||||
<div className="flex flex-col scroll-mt-30" id={key}>
|
<div className="flex flex-col scroll-mt-30" id={key}>
|
||||||
<div className="flex flex-col gap-2 md:-ml-9">
|
<div className="flex flex-col gap-2 md:-ml-9">
|
||||||
<Badges item={method} />
|
<Badges item={method} />
|
||||||
<CodeHeading href={`#${key}`}>
|
<CodeHeading
|
||||||
|
href={`#${key}`}
|
||||||
|
sourceLine={method.sourceLocation.fileLine}
|
||||||
|
sourceURL={method.sourceLocation.fileUrl}
|
||||||
|
>
|
||||||
{`${method.name}(${parametersString(method)})`}
|
{`${method.name}(${parametersString(method)})`}
|
||||||
<span>:</span>
|
<span>:</span>
|
||||||
<ExcerptText excerpt={method.returnTypeExcerpt} model={method.getAssociatedModel()!} />
|
<ExcerptText excerpt={method.returnTypeExcerpt} model={method.getAssociatedModel()!} />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import type { ApiItem } from '@discordjs/api-extractor-model';
|
||||||
import type { ApiItemJSON } from '@discordjs/api-extractor-utils';
|
import type { ApiItemJSON } from '@discordjs/api-extractor-utils';
|
||||||
import type { ApiItem } from '@microsoft/api-extractor-model';
|
|
||||||
import { createContext, useContext, useMemo, useState } from 'react';
|
import { createContext, useContext, useMemo, useState } from 'react';
|
||||||
import type { PropsWithChildren, Dispatch, SetStateAction } from 'react';
|
import type { PropsWithChildren, Dispatch, SetStateAction } from 'react';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ApiModel, ApiPackage } from '@microsoft/api-extractor-model';
|
import type { ApiModel, ApiPackage } from '@discordjs/api-extractor-model';
|
||||||
import { ApiItem } from '@microsoft/api-extractor-model';
|
import { ApiItem } from '@discordjs/api-extractor-model';
|
||||||
import { TSDocConfiguration } from '@microsoft/tsdoc';
|
import { TSDocConfiguration } from '@microsoft/tsdoc';
|
||||||
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
|
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ApiModel, ApiFunction } from '@microsoft/api-extractor-model';
|
import { ApiModel, ApiFunction } from '@discordjs/api-extractor-model';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import { fetchModelJSON } from '~/app/docAPI';
|
import { fetchModelJSON } from '~/app/docAPI';
|
||||||
import { addPackageToModel } from './addPackageToModel';
|
import { addPackageToModel } from './addPackageToModel';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ApiItem, ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
import type { ApiItem, ApiItemContainerMixin } from '@discordjs/api-extractor-model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves all inherited members (including merged members) of a given parent.
|
* Resolves all inherited members (including merged members) of a given parent.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
ApiModel,
|
ApiModel,
|
||||||
ApiParameterListMixin,
|
ApiParameterListMixin,
|
||||||
Excerpt,
|
Excerpt,
|
||||||
} from '@microsoft/api-extractor-model';
|
} from '@discordjs/api-extractor-model';
|
||||||
import type { DocSection } from '@microsoft/tsdoc';
|
import type { DocSection } from '@microsoft/tsdoc';
|
||||||
|
|
||||||
export function findMemberByKey(model: ApiModel, packageName: string, containerKey: string) {
|
export function findMemberByKey(model: ApiModel, packageName: string, containerKey: string) {
|
||||||
@@ -24,6 +24,7 @@ export function findMember(model: ApiModel, packageName: string, memberName: str
|
|||||||
interface ResolvedParameter {
|
interface ResolvedParameter {
|
||||||
description?: DocSection | undefined;
|
description?: DocSection | undefined;
|
||||||
isOptional: boolean;
|
isOptional: boolean;
|
||||||
|
isRest: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
parameterTypeExcerpt: Excerpt;
|
parameterTypeExcerpt: Excerpt;
|
||||||
}
|
}
|
||||||
@@ -45,6 +46,7 @@ export function resolveParameters(item: ApiDocumentedItem & ApiParameterListMixi
|
|||||||
name: param.tsdocParamBlock?.parameterName ?? tsdocAnalog?.parameterName ?? param.name,
|
name: param.tsdocParamBlock?.parameterName ?? tsdocAnalog?.parameterName ?? param.name,
|
||||||
description: param.tsdocParamBlock?.content ?? tsdocAnalog?.content,
|
description: param.tsdocParamBlock?.content ?? tsdocAnalog?.content,
|
||||||
isOptional: param.isOptional,
|
isOptional: param.isOptional,
|
||||||
|
isRest: param.isRest,
|
||||||
parameterTypeExcerpt: param.parameterTypeExcerpt,
|
parameterTypeExcerpt: param.parameterTypeExcerpt,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -93,6 +93,24 @@ export default [
|
|||||||
files: [`packages/voice/**/*${commonFiles}`],
|
files: [`packages/voice/**/*${commonFiles}`],
|
||||||
rules: { 'no-restricted-globals': 0 },
|
rules: { 'no-restricted-globals': 0 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: [`packages/api-extractor-model/**/*${commonFiles}`],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-namespace': 0,
|
||||||
|
'no-prototype-builtins': 0,
|
||||||
|
'consistent-this': 0,
|
||||||
|
'unicorn/no-this-assignment': 0,
|
||||||
|
'@typescript-eslint/no-this-alias': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [`packages/api-extractor/**/*${commonFiles}`],
|
||||||
|
rules: {
|
||||||
|
'consistent-this': 0,
|
||||||
|
'unicorn/no-this-assignment': 0,
|
||||||
|
'@typescript-eslint/no-this-alias': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
reactRuleset,
|
reactRuleset,
|
||||||
nextRuleset,
|
nextRuleset,
|
||||||
edgeRuleset,
|
edgeRuleset,
|
||||||
|
|||||||
23
packages/api-extractor-model/.gitignore
vendored
Normal file
23
packages/api-extractor-model/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Packages
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Dist
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
.turbo
|
||||||
|
.tmp
|
||||||
|
coverage
|
||||||
1
packages/api-extractor-model/.lintstagedrc.js
Normal file
1
packages/api-extractor-model/.lintstagedrc.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../.lintstagedrc.json');
|
||||||
30
packages/api-extractor-model/.npmignore
Normal file
30
packages/api-extractor-model/.npmignore
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# THIS IS A STANDARD TEMPLATE FOR .npmignore FILES IN THIS REPO.
|
||||||
|
|
||||||
|
# Ignore all files by default, to avoid accidentally publishing unintended files.
|
||||||
|
*
|
||||||
|
|
||||||
|
# Use negative patterns to bring back the specific things we want to publish.
|
||||||
|
!/bin/**
|
||||||
|
!/lib/**
|
||||||
|
!/lib-*/**
|
||||||
|
!/dist/**
|
||||||
|
!ThirdPartyNotice.txt
|
||||||
|
|
||||||
|
# Ignore certain patterns that should not get published.
|
||||||
|
/dist/*.stats.*
|
||||||
|
/lib/**/test/
|
||||||
|
/lib-*/**/test/
|
||||||
|
*.test.js
|
||||||
|
|
||||||
|
# NOTE: These don't need to be specified, because NPM includes them automatically.
|
||||||
|
#
|
||||||
|
# package.json
|
||||||
|
# README (and its variants)
|
||||||
|
# CHANGELOG (and its variants)
|
||||||
|
# LICENSE / LICENCE
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
# DO NOT MODIFY THE TEMPLATE ABOVE THIS LINE
|
||||||
|
#--------------------------------------------
|
||||||
|
|
||||||
|
# (Add your project-specific overrides here)
|
||||||
5
packages/api-extractor-model/.prettierignore
Normal file
5
packages/api-extractor-model/.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.turbo
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
CHANGELOG.md
|
||||||
|
tsup.config.bundled*
|
||||||
1
packages/api-extractor-model/.prettierrc.js
Normal file
1
packages/api-extractor-model/.prettierrc.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../.prettierrc.json');
|
||||||
2297
packages/api-extractor-model/CHANGELOG.json
Normal file
2297
packages/api-extractor-model/CHANGELOG.json
Normal file
File diff suppressed because it is too large
Load Diff
965
packages/api-extractor-model/CHANGELOG.md
Normal file
965
packages/api-extractor-model/CHANGELOG.md
Normal file
@@ -0,0 +1,965 @@
|
|||||||
|
# Change Log - @microsoft/api-extractor-model
|
||||||
|
|
||||||
|
This log was last generated on Thu, 28 Sep 2023 20:53:16 GMT and should not be manually modified.
|
||||||
|
|
||||||
|
## 7.28.2
|
||||||
|
Thu, 28 Sep 2023 20:53:16 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.28.1
|
||||||
|
Tue, 26 Sep 2023 09:30:33 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update type-only imports to include the type modifier.
|
||||||
|
|
||||||
|
## 7.28.0
|
||||||
|
Fri, 15 Sep 2023 00:36:58 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Update @types/node from 14 to 18
|
||||||
|
|
||||||
|
## 7.27.6
|
||||||
|
Tue, 08 Aug 2023 07:10:40 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.5
|
||||||
|
Wed, 19 Jul 2023 00:20:32 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.4
|
||||||
|
Thu, 06 Jul 2023 00:16:20 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.3
|
||||||
|
Thu, 15 Jun 2023 00:21:01 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.2
|
||||||
|
Wed, 07 Jun 2023 22:45:16 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.1
|
||||||
|
Mon, 29 May 2023 15:21:15 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.27.0
|
||||||
|
Mon, 22 May 2023 06:34:32 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Upgrade the TypeScript dependency to ~5.0.4
|
||||||
|
|
||||||
|
## 7.26.9
|
||||||
|
Fri, 12 May 2023 00:23:05 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.8
|
||||||
|
Thu, 04 May 2023 00:20:28 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix a mistake in the documentation for ApiParameterListMixin.overloadIndex
|
||||||
|
|
||||||
|
## 7.26.7
|
||||||
|
Mon, 01 May 2023 15:23:20 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.6
|
||||||
|
Sat, 29 Apr 2023 00:23:03 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.5
|
||||||
|
Thu, 27 Apr 2023 17:18:43 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.4
|
||||||
|
Fri, 10 Feb 2023 01:18:51 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.3
|
||||||
|
Sun, 05 Feb 2023 03:02:02 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.2
|
||||||
|
Wed, 01 Feb 2023 02:16:34 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.1
|
||||||
|
Mon, 30 Jan 2023 16:22:30 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.26.0
|
||||||
|
Wed, 25 Jan 2023 07:26:55 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add new .api.json field `isAbstract` to track `abstract` modifier in ApiClass, ApiMethod, and ApiProperty via ApiAbstractMixin (GitHub #3661)
|
||||||
|
|
||||||
|
## 7.25.3
|
||||||
|
Fri, 09 Dec 2022 16:18:28 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.25.2
|
||||||
|
Wed, 26 Oct 2022 00:16:16 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update the @microsoft/tsdoc dependency version to 0.14.2.
|
||||||
|
|
||||||
|
## 7.25.1
|
||||||
|
Thu, 13 Oct 2022 00:20:15 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.25.0
|
||||||
|
Tue, 11 Oct 2022 23:49:12 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add a new fileUrlPath property to relevant API items and serialize this to the .api.json. Additionally, add a SourceFile helper class for constructing file URLs from these paths and the projectFolderUrl.
|
||||||
|
|
||||||
|
## 7.24.4
|
||||||
|
Mon, 10 Oct 2022 15:23:44 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.24.3
|
||||||
|
Thu, 29 Sep 2022 07:13:06 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.24.2
|
||||||
|
Wed, 21 Sep 2022 20:21:10 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.24.1
|
||||||
|
Thu, 15 Sep 2022 00:18:52 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.24.0
|
||||||
|
Fri, 02 Sep 2022 17:48:42 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add new ApiExportedMixin mixin class for determining whether an API item is exported or not
|
||||||
|
|
||||||
|
## 7.23.3
|
||||||
|
Wed, 24 Aug 2022 03:01:22 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.23.2
|
||||||
|
Wed, 24 Aug 2022 00:14:38 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Remove use of LegacyAdapters.sortStable
|
||||||
|
|
||||||
|
## 7.23.1
|
||||||
|
Fri, 19 Aug 2022 00:17:19 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.23.0
|
||||||
|
Wed, 03 Aug 2022 18:40:35 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Upgrade TypeScript dependency to 4.7
|
||||||
|
|
||||||
|
## 7.22.2
|
||||||
|
Mon, 01 Aug 2022 02:45:32 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.22.1
|
||||||
|
Thu, 21 Jul 2022 23:30:27 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Improve IFindApiItemMessage and fix two small bugs with ApiItemContainerMixin.findMembersWithInheritance()
|
||||||
|
|
||||||
|
## 7.22.0
|
||||||
|
Thu, 21 Jul 2022 00:16:14 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add a new ApiItemContainerMixin.findMembersWithInheritance() method for finding an item's inherited members
|
||||||
|
|
||||||
|
## 7.21.0
|
||||||
|
Thu, 30 Jun 2022 04:48:53 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Update model to reflect that index signatures can also be readonly
|
||||||
|
|
||||||
|
## 7.20.3
|
||||||
|
Tue, 28 Jun 2022 22:47:13 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.20.2
|
||||||
|
Tue, 28 Jun 2022 00:23:32 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.20.1
|
||||||
|
Mon, 27 Jun 2022 18:43:09 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.20.0
|
||||||
|
Sat, 25 Jun 2022 21:00:40 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add a new initializerTokenRange field to ApiProperty and ApiVariable items.
|
||||||
|
|
||||||
|
## 7.19.1
|
||||||
|
Sat, 25 Jun 2022 01:54:29 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.19.0
|
||||||
|
Fri, 24 Jun 2022 07:16:47 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Added new configuration for ItemContainerMixin member ordering
|
||||||
|
|
||||||
|
## 7.18.2
|
||||||
|
Fri, 17 Jun 2022 09:17:54 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.18.1
|
||||||
|
Fri, 17 Jun 2022 00:16:18 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.18.0
|
||||||
|
Tue, 07 Jun 2022 09:37:04 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add an "isReadonly" field to ApiProperty, ApiPropertySignature, and ApiVariable
|
||||||
|
- Add an "isProtected" field to ApiConstructor, ApiMethod, and ApiProperty
|
||||||
|
|
||||||
|
## 7.17.3
|
||||||
|
Tue, 10 May 2022 01:20:43 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.17.2
|
||||||
|
Sat, 23 Apr 2022 02:13:07 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.17.1
|
||||||
|
Fri, 15 Apr 2022 00:12:36 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.17.0
|
||||||
|
Wed, 13 Apr 2022 15:12:40 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add a new isOptional property to TypeParameters deserialized from the .api.json file with api-extractor-model.
|
||||||
|
|
||||||
|
## 7.16.2
|
||||||
|
Tue, 12 Apr 2022 02:58:32 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update TSDoc dependencies.
|
||||||
|
|
||||||
|
## 7.16.1
|
||||||
|
Sat, 09 Apr 2022 02:24:26 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Rename the "master" branch to "main".
|
||||||
|
- Update a path in the README.
|
||||||
|
|
||||||
|
## 7.16.0
|
||||||
|
Thu, 31 Mar 2022 02:06:05 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Updated api-extractor-model to store whether a parameter is optional.
|
||||||
|
|
||||||
|
## 7.15.4
|
||||||
|
Tue, 15 Mar 2022 19:15:53 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.15.3
|
||||||
|
Wed, 05 Jan 2022 16:07:47 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.15.2
|
||||||
|
Mon, 27 Dec 2021 16:10:40 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.15.1
|
||||||
|
Thu, 09 Dec 2021 20:34:41 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.15.0
|
||||||
|
Thu, 09 Dec 2021 00:21:54 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Replace const enums with conventional enums to allow for compatibility with JavaScript consumers.
|
||||||
|
|
||||||
|
## 7.14.0
|
||||||
|
Wed, 08 Dec 2021 16:14:05 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Update to TypeScript 4.5
|
||||||
|
|
||||||
|
## 7.13.18
|
||||||
|
Mon, 06 Dec 2021 16:08:33 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.17
|
||||||
|
Fri, 03 Dec 2021 03:05:22 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.16
|
||||||
|
Sat, 06 Nov 2021 00:09:13 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.15
|
||||||
|
Fri, 05 Nov 2021 15:09:18 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.14
|
||||||
|
Wed, 27 Oct 2021 00:08:15 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update the package.json repository field to include the directory property.
|
||||||
|
|
||||||
|
## 7.13.13
|
||||||
|
Wed, 13 Oct 2021 15:09:54 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.12
|
||||||
|
Fri, 08 Oct 2021 08:08:34 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.11
|
||||||
|
Thu, 07 Oct 2021 07:13:35 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.10
|
||||||
|
Tue, 05 Oct 2021 15:08:38 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.9
|
||||||
|
Fri, 24 Sep 2021 00:09:29 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.8
|
||||||
|
Thu, 23 Sep 2021 00:10:40 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Upgrade the `@types/node` dependency to version to version 12.
|
||||||
|
|
||||||
|
## 7.13.7
|
||||||
|
Tue, 14 Sep 2021 01:17:04 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.6
|
||||||
|
Mon, 13 Sep 2021 15:07:06 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.5
|
||||||
|
Wed, 11 Aug 2021 00:07:21 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.4
|
||||||
|
Mon, 12 Jul 2021 23:08:26 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.3
|
||||||
|
Fri, 04 Jun 2021 19:59:53 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.2
|
||||||
|
Wed, 19 May 2021 00:11:39 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.1
|
||||||
|
Mon, 03 May 2021 15:10:29 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.13.0
|
||||||
|
Tue, 20 Apr 2021 04:59:51 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- The .api.json file format now stores the TSDoc configuration used for parsing doc comments
|
||||||
|
|
||||||
|
## 7.12.5
|
||||||
|
Mon, 12 Apr 2021 15:10:28 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.12.4
|
||||||
|
Thu, 08 Apr 2021 06:05:31 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix minor typo in README.md
|
||||||
|
|
||||||
|
## 7.12.3
|
||||||
|
Tue, 06 Apr 2021 15:14:22 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.12.2
|
||||||
|
Fri, 05 Feb 2021 16:10:42 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.12.1
|
||||||
|
Thu, 10 Dec 2020 23:25:49 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Enable support for @decorator
|
||||||
|
|
||||||
|
## 7.12.0
|
||||||
|
Wed, 18 Nov 2020 08:19:54 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Introduce an ApiOptionalMixin base class for representing optional properties and methods
|
||||||
|
|
||||||
|
## 7.11.0
|
||||||
|
Wed, 18 Nov 2020 06:21:57 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Update .api.json file format to store a new field "isOptional" for documenting optional properties
|
||||||
|
|
||||||
|
## 7.10.10
|
||||||
|
Wed, 11 Nov 2020 01:08:59 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.9
|
||||||
|
Tue, 10 Nov 2020 23:13:12 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.8
|
||||||
|
Fri, 30 Oct 2020 06:38:39 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.7
|
||||||
|
Fri, 30 Oct 2020 00:10:14 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.6
|
||||||
|
Thu, 29 Oct 2020 06:14:19 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix .d.ts error when the library is imported by a project using TypeScript 4.0
|
||||||
|
|
||||||
|
## 7.10.5
|
||||||
|
Wed, 28 Oct 2020 01:18:03 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.4
|
||||||
|
Tue, 27 Oct 2020 15:10:14 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.3
|
||||||
|
Tue, 06 Oct 2020 00:24:06 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.2
|
||||||
|
Mon, 05 Oct 2020 22:36:57 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.10.1
|
||||||
|
Wed, 30 Sep 2020 18:39:17 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update to build with @rushstack/heft-node-rig
|
||||||
|
|
||||||
|
## 7.10.0
|
||||||
|
Wed, 30 Sep 2020 06:53:53 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Upgrade compiler; the API now requires TypeScript 3.9 or newer
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update README.md
|
||||||
|
|
||||||
|
## 7.9.7
|
||||||
|
Tue, 22 Sep 2020 05:45:57 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.6
|
||||||
|
Tue, 22 Sep 2020 01:45:31 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.5
|
||||||
|
Tue, 22 Sep 2020 00:08:53 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.4
|
||||||
|
Sat, 19 Sep 2020 04:37:27 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.3
|
||||||
|
Sat, 19 Sep 2020 03:33:07 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.2
|
||||||
|
Fri, 18 Sep 2020 22:57:24 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.1
|
||||||
|
Fri, 18 Sep 2020 21:49:54 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.9.0
|
||||||
|
Sun, 13 Sep 2020 01:53:20 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add support for system selectors in declaration references
|
||||||
|
|
||||||
|
## 7.8.22
|
||||||
|
Fri, 11 Sep 2020 02:13:35 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.21
|
||||||
|
Mon, 07 Sep 2020 07:37:37 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.20
|
||||||
|
Sat, 05 Sep 2020 18:56:34 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix "Converting circular structure to JSON" error (GitHub #2152)
|
||||||
|
|
||||||
|
## 7.8.19
|
||||||
|
Thu, 27 Aug 2020 11:27:06 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.18
|
||||||
|
Mon, 24 Aug 2020 07:35:20 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.17
|
||||||
|
Sat, 22 Aug 2020 05:55:43 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.16
|
||||||
|
Tue, 18 Aug 2020 23:59:42 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.15
|
||||||
|
Mon, 17 Aug 2020 04:53:23 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.14
|
||||||
|
Wed, 12 Aug 2020 00:10:05 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Updated project to build with Heft
|
||||||
|
|
||||||
|
## 7.8.13
|
||||||
|
Wed, 05 Aug 2020 18:27:33 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.12
|
||||||
|
Fri, 03 Jul 2020 15:09:04 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.11
|
||||||
|
Thu, 25 Jun 2020 06:43:35 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.10
|
||||||
|
Wed, 24 Jun 2020 09:50:48 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.9
|
||||||
|
Wed, 24 Jun 2020 09:04:28 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.8
|
||||||
|
Wed, 10 Jun 2020 20:48:30 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.7
|
||||||
|
Sat, 30 May 2020 02:59:54 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.6
|
||||||
|
Thu, 28 May 2020 05:59:02 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.5
|
||||||
|
Wed, 27 May 2020 05:15:11 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.4
|
||||||
|
Tue, 26 May 2020 23:00:25 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.3
|
||||||
|
Fri, 22 May 2020 15:08:43 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.2
|
||||||
|
Thu, 21 May 2020 23:09:44 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.1
|
||||||
|
Thu, 21 May 2020 15:42:00 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.8.0
|
||||||
|
Wed, 06 May 2020 08:23:45 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Enable canonicalReference to ApiItem lookup
|
||||||
|
|
||||||
|
## 7.7.11
|
||||||
|
Wed, 08 Apr 2020 04:07:33 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.10
|
||||||
|
Sat, 28 Mar 2020 00:37:16 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Upgrade to TSdoc 0.12.19
|
||||||
|
|
||||||
|
## 7.7.9
|
||||||
|
Wed, 18 Mar 2020 15:07:47 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Upgrade cyclic dependencies
|
||||||
|
|
||||||
|
## 7.7.8
|
||||||
|
Tue, 17 Mar 2020 23:55:58 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Replace dependencies whose NPM scope was renamed from `@microsoft` to `@rushstack`
|
||||||
|
|
||||||
|
## 7.7.7
|
||||||
|
Tue, 28 Jan 2020 02:23:44 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.6
|
||||||
|
Thu, 23 Jan 2020 01:07:56 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.5
|
||||||
|
Tue, 21 Jan 2020 21:56:14 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.4
|
||||||
|
Sun, 19 Jan 2020 02:26:52 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Upgrade Node typings to Node 10
|
||||||
|
|
||||||
|
## 7.7.3
|
||||||
|
Fri, 17 Jan 2020 01:08:23 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.2
|
||||||
|
Thu, 09 Jan 2020 06:44:13 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.1
|
||||||
|
Wed, 08 Jan 2020 00:11:31 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.7.0
|
||||||
|
Tue, 03 Dec 2019 03:17:43 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Improve declaration reference syntax to allow linking to overloaded functions/methods
|
||||||
|
|
||||||
|
## 7.6.0
|
||||||
|
Sun, 24 Nov 2019 00:54:04 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Added support for `@throws`
|
||||||
|
|
||||||
|
## 7.5.6
|
||||||
|
Fri, 15 Nov 2019 04:50:50 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.5.5
|
||||||
|
Mon, 11 Nov 2019 16:07:56 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.5.4
|
||||||
|
Tue, 05 Nov 2019 06:49:28 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix an issue where API reports sometimes were ordered differently depending on the version of NodeJS (GitHub #1552)
|
||||||
|
|
||||||
|
## 7.5.3
|
||||||
|
Tue, 05 Nov 2019 01:08:39 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Clarified an error message
|
||||||
|
|
||||||
|
## 7.5.2
|
||||||
|
Tue, 22 Oct 2019 06:24:44 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Refactor some code as part of migration from TSLint to ESLint
|
||||||
|
|
||||||
|
## 7.5.1
|
||||||
|
Sun, 29 Sep 2019 23:56:29 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update repository URL
|
||||||
|
|
||||||
|
## 7.5.0
|
||||||
|
Wed, 25 Sep 2019 15:15:31 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add ApiItem.getMergedSiblings() API
|
||||||
|
|
||||||
|
## 7.4.2
|
||||||
|
Mon, 23 Sep 2019 15:14:55 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Remove unnecessary dependency on @types/node
|
||||||
|
|
||||||
|
## 7.4.1
|
||||||
|
Tue, 10 Sep 2019 22:32:23 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update documentation
|
||||||
|
|
||||||
|
## 7.4.0
|
||||||
|
Tue, 10 Sep 2019 20:38:33 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add 'canonicalReference' to ExcerptToken
|
||||||
|
|
||||||
|
## 7.3.4
|
||||||
|
Wed, 04 Sep 2019 18:28:06 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.3.3
|
||||||
|
Wed, 04 Sep 2019 15:15:37 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Update TSDoc dependency to 0.12.14
|
||||||
|
|
||||||
|
## 7.3.2
|
||||||
|
Thu, 08 Aug 2019 15:14:17 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.3.1
|
||||||
|
Thu, 08 Aug 2019 00:49:05 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- (Experimental) Add ApiExtractor.canonicalReference which is a beta implementation of the revised TSDoc declaration reference notation
|
||||||
|
|
||||||
|
## 7.3.0
|
||||||
|
Mon, 22 Jul 2019 19:13:10 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Rename `ApiItem.canonicalReference` to `.containerKey`; rename `ApiItemContainerMixin.tryGetMember()` to `.tryGetMemberByKey()`; rename `Api___.getCanonicalReference()` to `.getContainerKey()`
|
||||||
|
|
||||||
|
## 7.2.0
|
||||||
|
Tue, 11 Jun 2019 00:48:06 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Add API support for type parameters and type alias types
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Improve the .api.json deserializer to validate the schema version and support backwards compatibility
|
||||||
|
|
||||||
|
## 7.1.3
|
||||||
|
Wed, 05 Jun 2019 19:12:34 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix an issue where TSDoc index selectors (ApiParameterListMixin.overloadIndex) started from 0, whereas TSDoc requires a nonzero number
|
||||||
|
|
||||||
|
## 7.1.2
|
||||||
|
Tue, 04 Jun 2019 05:51:53 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Fix an issue where ApiConstructor inherited from ApiStaticMixin, but TypeScript constructors cannot be static
|
||||||
|
|
||||||
|
## 7.1.1
|
||||||
|
Mon, 27 May 2019 04:13:44 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Make the strings returned by ApiItem.displayName less verbose
|
||||||
|
- Improve formatting of the strings returned by ApiItem.getScopedNameWithinPackage()
|
||||||
|
|
||||||
|
## 7.1.0
|
||||||
|
Tue, 16 Apr 2019 11:01:37 GMT
|
||||||
|
|
||||||
|
### Minor changes
|
||||||
|
|
||||||
|
- Initial stable release of API Extractor 7
|
||||||
|
|
||||||
|
## 7.0.28
|
||||||
|
Wed, 20 Mar 2019 19:14:49 GMT
|
||||||
|
|
||||||
|
_Version update only_
|
||||||
|
|
||||||
|
## 7.0.27
|
||||||
|
Mon, 18 Mar 2019 04:28:43 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Add helper functions for ReleaseTag
|
||||||
|
- Export IApiItemConstructor to eliminate the ae-forgotten-export warning
|
||||||
|
|
||||||
|
## 7.0.26
|
||||||
|
Wed, 13 Mar 2019 19:13:14 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Refactor code to move the IndentedWriter API from api-extractor-model to api-documenter
|
||||||
|
|
||||||
|
## 7.0.25
|
||||||
|
Wed, 13 Mar 2019 01:14:05 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Upgrade TSDoc
|
||||||
|
|
||||||
|
## 7.0.24
|
||||||
|
Mon, 11 Mar 2019 16:13:36 GMT
|
||||||
|
|
||||||
|
### Patches
|
||||||
|
|
||||||
|
- Initial setup of new package @microsoft/api-extractor-model
|
||||||
|
|
||||||
24
packages/api-extractor-model/LICENSE
Normal file
24
packages/api-extractor-model/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
@microsoft/api-extractor
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
67
packages/api-extractor-model/README.md
Normal file
67
packages/api-extractor-model/README.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# @microsoft/api-extractor-model
|
||||||
|
|
||||||
|
Use this library to read and write \*.api.json files as defined by the [API Extractor](https://api-extractor.com/) tool.
|
||||||
|
These files are used to generate a documentation website for your TypeScript package. The files store the
|
||||||
|
API signatures and doc comments that were extracted from your package.
|
||||||
|
|
||||||
|
API documentation for this package: https://rushstack.io/pages/api/api-extractor-model/
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following code sample shows how to load `example.api.json`, which would be generated by API Extractor
|
||||||
|
when it analyzes a hypothetical NPM package called `example`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { ApiModel, ApiPackage } from '@discordjs/api-extractor-model';
|
||||||
|
|
||||||
|
const apiModel: ApiModel = new ApiModel();
|
||||||
|
const apiPackage: ApiPackage = apiModel.loadPackage('example.api.json');
|
||||||
|
|
||||||
|
for (const member of apiPackage.members) {
|
||||||
|
console.log(member.displayName);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `ApiModel` is acts as a container for various packages that are loaded and operated on as a group.
|
||||||
|
For example, a documentation tool may need to resolve `@link` references across different packages.
|
||||||
|
In this case we would load the various packages into the `ApiModel`, and then use
|
||||||
|
the `ApiModel.resolveDeclarationReference()` to resolve the `@link` targets.
|
||||||
|
|
||||||
|
The data structure forms a tree of various classes that start with the `Api` prefix. The nesting hierarchy
|
||||||
|
might look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
- ApiModel
|
||||||
|
- ApiPackage
|
||||||
|
- ApiEntryPoint
|
||||||
|
- ApiClass
|
||||||
|
- ApiMethod
|
||||||
|
- ApiProperty
|
||||||
|
- ApiEnum
|
||||||
|
- ApiEnumMember
|
||||||
|
- ApiInterface
|
||||||
|
- ApiMethodSignature
|
||||||
|
- ApiPropertySignature
|
||||||
|
- ApiNamespace
|
||||||
|
- (ApiClass, ApiEnum, ApiInterface, ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `ApiItem.members` property to traverse this tree.
|
||||||
|
|
||||||
|
Note that the non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
a namespace containing static members of the class.
|
||||||
|
|
||||||
|
> For a complete project that uses these APIs to generate an API reference web site,
|
||||||
|
> see the [@microsoft/api-documenter](https://www.npmjs.com/package/@microsoft/api-documenter) source code.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- [CHANGELOG.md](https://github.com/microsoft/rushstack/blob/main/libraries/api-extractor-model/CHANGELOG.md) - Find
|
||||||
|
out what's new in the latest version
|
||||||
|
- [API Reference](https://rushstack.io/pages/api/api-extractor-model/)
|
||||||
|
|
||||||
|
API Extractor is part of the [Rush Stack](https://rushstack.io/) family of projects.
|
||||||
20
packages/api-extractor-model/config/api-extractor.json
Normal file
20
packages/api-extractor-model/config/api-extractor.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||||
|
|
||||||
|
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
|
||||||
|
|
||||||
|
"apiReport": {
|
||||||
|
"enabled": true,
|
||||||
|
"reportFolder": "../../../common/reviews/api"
|
||||||
|
},
|
||||||
|
|
||||||
|
"docModel": {
|
||||||
|
"enabled": true,
|
||||||
|
"apiJsonFilePath": "../../../common/temp/api/<unscopedPackageName>.api.json"
|
||||||
|
},
|
||||||
|
|
||||||
|
"dtsRollup": {
|
||||||
|
"enabled": true,
|
||||||
|
"untrimmedFilePath": "<projectFolder>/dist/rollup.d.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
packages/api-extractor-model/config/jest.config.json
Normal file
11
packages/api-extractor-model/config/jest.config.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": "@rushstack/heft-node-rig/profiles/default/config/jest.config.json",
|
||||||
|
|
||||||
|
// Enable code coverage for Jest
|
||||||
|
"collectCoverage": true,
|
||||||
|
"coverageDirectory": "<rootDir>/coverage",
|
||||||
|
"coverageReporters": ["cobertura", "html"],
|
||||||
|
|
||||||
|
// Use v8 coverage provider to avoid Babel
|
||||||
|
"coverageProvider": "v8"
|
||||||
|
}
|
||||||
49
packages/api-extractor-model/package.json
Normal file
49
packages/api-extractor-model/package.json
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "@discordjs/api-extractor-model",
|
||||||
|
"version": "7.28.2",
|
||||||
|
"description": "A helper library for loading and saving the .api.json files created by API Extractor",
|
||||||
|
"private": true,
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/discordjs/discord.js.git",
|
||||||
|
"directory": "packages/api-extractor-model"
|
||||||
|
},
|
||||||
|
"homepage": "https://discord.js.org",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --noEmit && tsup",
|
||||||
|
"lint": "prettier --check . && cross-env TIMING=1 eslint --format=pretty src",
|
||||||
|
"format": "prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"require": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"import": {
|
||||||
|
"types": "./dist/index.d.mts",
|
||||||
|
"default": "./dist/index.mjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/tsdoc": "0.14.2",
|
||||||
|
"@microsoft/tsdoc-config": "0.16.2",
|
||||||
|
"@rushstack/node-core-library": "3.61.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.18.8",
|
||||||
|
"@types/jest": "^29.5.7",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^8.53.0",
|
||||||
|
"eslint-config-neon": "^0.1.57",
|
||||||
|
"eslint-formatter-pretty": "^5.0.0",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"tsup": "^7.2.0",
|
||||||
|
"turbo": "^1.10.16"
|
||||||
|
}
|
||||||
|
}
|
||||||
68
packages/api-extractor-model/src/aedoc/AedocDefinitions.ts
Normal file
68
packages/api-extractor-model/src/aedoc/AedocDefinitions.ts
Normal file
@@ -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 { TSDocConfiguration, TSDocTagDefinition, TSDocTagSyntaxKind, StandardTags } from '@microsoft/tsdoc';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @deprecated - tsdoc configuration is now constructed from tsdoc.json files associated with each package.
|
||||||
|
*/
|
||||||
|
export class AedocDefinitions {
|
||||||
|
public static readonly betaDocumentation: TSDocTagDefinition = new TSDocTagDefinition({
|
||||||
|
tagName: '@betaDocumentation',
|
||||||
|
syntaxKind: TSDocTagSyntaxKind.ModifierTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly internalRemarks: TSDocTagDefinition = new TSDocTagDefinition({
|
||||||
|
tagName: '@internalRemarks',
|
||||||
|
syntaxKind: TSDocTagSyntaxKind.BlockTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly preapprovedTag: TSDocTagDefinition = new TSDocTagDefinition({
|
||||||
|
tagName: '@preapproved',
|
||||||
|
syntaxKind: TSDocTagSyntaxKind.ModifierTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
public static get tsdocConfiguration(): TSDocConfiguration {
|
||||||
|
if (!AedocDefinitions._tsdocConfiguration) {
|
||||||
|
const configuration: TSDocConfiguration = new TSDocConfiguration();
|
||||||
|
configuration.addTagDefinitions(
|
||||||
|
[AedocDefinitions.betaDocumentation, AedocDefinitions.internalRemarks, AedocDefinitions.preapprovedTag],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
configuration.setSupportForTags(
|
||||||
|
[
|
||||||
|
StandardTags.alpha,
|
||||||
|
StandardTags.beta,
|
||||||
|
StandardTags.decorator,
|
||||||
|
StandardTags.defaultValue,
|
||||||
|
StandardTags.deprecated,
|
||||||
|
StandardTags.eventProperty,
|
||||||
|
StandardTags.example,
|
||||||
|
StandardTags.inheritDoc,
|
||||||
|
StandardTags.internal,
|
||||||
|
StandardTags.link,
|
||||||
|
StandardTags.override,
|
||||||
|
StandardTags.packageDocumentation,
|
||||||
|
StandardTags.param,
|
||||||
|
StandardTags.privateRemarks,
|
||||||
|
StandardTags.public,
|
||||||
|
StandardTags.readonly,
|
||||||
|
StandardTags.remarks,
|
||||||
|
StandardTags.returns,
|
||||||
|
StandardTags.sealed,
|
||||||
|
StandardTags.throws,
|
||||||
|
StandardTags.virtual,
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
AedocDefinitions._tsdocConfiguration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AedocDefinitions._tsdocConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static _tsdocConfiguration: TSDocConfiguration | undefined;
|
||||||
|
}
|
||||||
88
packages/api-extractor-model/src/aedoc/ReleaseTag.ts
Normal file
88
packages/api-extractor-model/src/aedoc/ReleaseTag.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "release tag" is a custom TSDoc tag that is applied to an API to communicate the level of support
|
||||||
|
* provided for third-party developers.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The four release tags are: `@internal`, `@alpha`, `@beta`, and `@public`. They are applied to API items such
|
||||||
|
* as classes, member functions, enums, etc. The release tag applies recursively to members of a container
|
||||||
|
* (e.g. class or interface). For example, if a class is marked as `@beta`, then all of its members automatically
|
||||||
|
* have this status; you DON'T need add the `@beta` tag to each member function. However, you could add
|
||||||
|
* `@internal` to a member function to give it a different release status.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export enum ReleaseTag {
|
||||||
|
/**
|
||||||
|
* No release tag was specified in the AEDoc summary.
|
||||||
|
*/
|
||||||
|
None = 0,
|
||||||
|
/**
|
||||||
|
* Indicates that an API item is meant only for usage by other NPM packages from the same
|
||||||
|
* maintainer. Third parties should never use "internal" APIs. (To emphasize this, their
|
||||||
|
* names are prefixed by underscores.)
|
||||||
|
*/
|
||||||
|
Internal = 1,
|
||||||
|
/**
|
||||||
|
* Indicates that an API item is eventually intended to be public, but currently is in an
|
||||||
|
* early stage of development. Third parties should not use "alpha" APIs.
|
||||||
|
*/
|
||||||
|
Alpha = 2,
|
||||||
|
/**
|
||||||
|
* Indicates that an API item has been released in an experimental state. Third parties are
|
||||||
|
* encouraged to try it and provide feedback. However, a "beta" API should NOT be used
|
||||||
|
* in production.
|
||||||
|
*/
|
||||||
|
Beta = 3,
|
||||||
|
/**
|
||||||
|
* Indicates that an API item has been officially released. It is part of the supported
|
||||||
|
* contract (e.g. SemVer) for a package.
|
||||||
|
*/
|
||||||
|
Public = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper functions for working with the `ReleaseTag` enum.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
// export namespace ReleaseTag {
|
||||||
|
/**
|
||||||
|
* Returns the TSDoc tag name for a `ReleaseTag` value.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* For example, `getTagName(ReleaseTag.Internal)` would return the string `@internal`.
|
||||||
|
*/
|
||||||
|
export function getTagName(releaseTag: ReleaseTag): string {
|
||||||
|
switch (releaseTag) {
|
||||||
|
case ReleaseTag.None:
|
||||||
|
return '(none)';
|
||||||
|
case ReleaseTag.Internal:
|
||||||
|
return '@internal';
|
||||||
|
case ReleaseTag.Alpha:
|
||||||
|
return '@alpha';
|
||||||
|
case ReleaseTag.Beta:
|
||||||
|
return '@beta';
|
||||||
|
case ReleaseTag.Public:
|
||||||
|
return '@public';
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported release tag');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two `ReleaseTag` values. Their values must not be `ReleaseTag.None`.
|
||||||
|
*
|
||||||
|
* @returns 0 if `a` and `b` are equal, a positive number if `a` is more public than `b`,
|
||||||
|
* and a negative number if `a` is less public than `b`.
|
||||||
|
* @remarks
|
||||||
|
* For example, `compareReleaseTag(ReleaseTag.Beta, ReleaseTag.Alpha)` will return a positive
|
||||||
|
* number because beta is more public than alpha.
|
||||||
|
*/
|
||||||
|
export function compare(a: ReleaseTag, b: ReleaseTag): number {
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
// }
|
||||||
84
packages/api-extractor-model/src/index.ts
Normal file
84
packages/api-extractor-model/src/index.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this library to read and write *.api.json files as defined by the
|
||||||
|
* {@link https://api-extractor.com/ | API Extractor} tool. These files are used to generate a documentation
|
||||||
|
* website for your TypeScript package. The files store the API signatures and doc comments that were extracted
|
||||||
|
* from your package.
|
||||||
|
*
|
||||||
|
* @packageDocumentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { AedocDefinitions } from './aedoc/AedocDefinitions.js';
|
||||||
|
export { ReleaseTag, compare as releaseTagCompare, getTagName as releaseTagGetTagName } from './aedoc/ReleaseTag.js';
|
||||||
|
|
||||||
|
// items
|
||||||
|
export { type IApiDeclaredItemOptions, ApiDeclaredItem } from './items/ApiDeclaredItem.js';
|
||||||
|
export { type IApiDocumentedItemOptions, ApiDocumentedItem } from './items/ApiDocumentedItem.js';
|
||||||
|
export { ApiItemKind, type IApiItemOptions, ApiItem, type IApiItemConstructor } from './items/ApiItem.js';
|
||||||
|
export { type IApiPropertyItemOptions, ApiPropertyItem } from './items/ApiPropertyItem.js';
|
||||||
|
|
||||||
|
// mixins
|
||||||
|
export {
|
||||||
|
type IApiParameterListMixinOptions,
|
||||||
|
type IApiParameterOptions,
|
||||||
|
ApiParameterListMixin,
|
||||||
|
} from './mixins/ApiParameterListMixin.js';
|
||||||
|
export {
|
||||||
|
type IApiTypeParameterOptions,
|
||||||
|
type IApiTypeParameterListMixinOptions,
|
||||||
|
ApiTypeParameterListMixin,
|
||||||
|
} from './mixins/ApiTypeParameterListMixin.js';
|
||||||
|
export { type IApiAbstractMixinOptions, ApiAbstractMixin } from './mixins/ApiAbstractMixin.js';
|
||||||
|
export { type IApiItemContainerMixinOptions, ApiItemContainerMixin } from './mixins/ApiItemContainerMixin.js';
|
||||||
|
export { type IApiProtectedMixinOptions, ApiProtectedMixin } from './mixins/ApiProtectedMixin.js';
|
||||||
|
export { type IApiReleaseTagMixinOptions, ApiReleaseTagMixin } from './mixins/ApiReleaseTagMixin.js';
|
||||||
|
export { type IApiReturnTypeMixinOptions, ApiReturnTypeMixin } from './mixins/ApiReturnTypeMixin.js';
|
||||||
|
export { type IApiStaticMixinOptions, ApiStaticMixin } from './mixins/ApiStaticMixin.js';
|
||||||
|
export { type IApiNameMixinOptions, ApiNameMixin } from './mixins/ApiNameMixin.js';
|
||||||
|
export { type IApiOptionalMixinOptions, ApiOptionalMixin } from './mixins/ApiOptionalMixin.js';
|
||||||
|
export { type IApiReadonlyMixinOptions, ApiReadonlyMixin } from './mixins/ApiReadonlyMixin.js';
|
||||||
|
export { type IApiInitializerMixinOptions, ApiInitializerMixin } from './mixins/ApiInitializerMixin.js';
|
||||||
|
export { type IApiExportedMixinOptions, ApiExportedMixin } from './mixins/ApiExportedMixin.js';
|
||||||
|
export {
|
||||||
|
type IFindApiItemsResult,
|
||||||
|
type IFindApiItemsMessage,
|
||||||
|
FindApiItemsMessageId,
|
||||||
|
} from './mixins/IFindApiItemsResult.js';
|
||||||
|
|
||||||
|
export {
|
||||||
|
ExcerptTokenKind,
|
||||||
|
type IExcerptTokenRange,
|
||||||
|
type IExcerptToken,
|
||||||
|
ExcerptToken,
|
||||||
|
Excerpt,
|
||||||
|
} from './mixins/Excerpt.js';
|
||||||
|
export type { Constructor, PropertiesOf } from './mixins/Mixin.js';
|
||||||
|
|
||||||
|
// model
|
||||||
|
export { type IApiCallSignatureOptions, ApiCallSignature } from './model/ApiCallSignature.js';
|
||||||
|
export { type IApiClassOptions, ApiClass } from './model/ApiClass.js';
|
||||||
|
export { type IApiConstructorOptions, ApiConstructor } from './model/ApiConstructor.js';
|
||||||
|
export { type IApiConstructSignatureOptions, ApiConstructSignature } from './model/ApiConstructSignature.js';
|
||||||
|
export { type IApiEntryPointOptions, ApiEntryPoint } from './model/ApiEntryPoint.js';
|
||||||
|
export { type IApiEnumOptions, ApiEnum } from './model/ApiEnum.js';
|
||||||
|
export { type IApiEnumMemberOptions, ApiEnumMember, EnumMemberOrder } from './model/ApiEnumMember.js';
|
||||||
|
export { type IApiFunctionOptions, ApiFunction } from './model/ApiFunction.js';
|
||||||
|
export { type IApiIndexSignatureOptions, ApiIndexSignature } from './model/ApiIndexSignature.js';
|
||||||
|
export { type IApiInterfaceOptions, ApiInterface } from './model/ApiInterface.js';
|
||||||
|
export { type IApiMethodOptions, ApiMethod } from './model/ApiMethod.js';
|
||||||
|
export { type IApiMethodSignatureOptions, ApiMethodSignature } from './model/ApiMethodSignature.js';
|
||||||
|
export { ApiModel } from './model/ApiModel.js';
|
||||||
|
export { type IApiNamespaceOptions, ApiNamespace } from './model/ApiNamespace.js';
|
||||||
|
export { type IApiPackageOptions, ApiPackage, type IApiPackageSaveOptions } from './model/ApiPackage.js';
|
||||||
|
export { type IParameterOptions, Parameter } from './model/Parameter.js';
|
||||||
|
export { type IApiPropertyOptions, ApiProperty } from './model/ApiProperty.js';
|
||||||
|
export { type IApiPropertySignatureOptions, ApiPropertySignature } from './model/ApiPropertySignature.js';
|
||||||
|
export { type IApiTypeAliasOptions, ApiTypeAlias } from './model/ApiTypeAlias.js';
|
||||||
|
export { type ITypeParameterOptions, TypeParameter } from './model/TypeParameter.js';
|
||||||
|
export { type IApiVariableOptions, ApiVariable } from './model/ApiVariable.js';
|
||||||
|
export type { IResolveDeclarationReferenceResult } from './model/ModelReferenceResolver.js';
|
||||||
|
export { HeritageType } from './model/HeritageType.js';
|
||||||
|
export { type ISourceLocationOptions, SourceLocation } from './model/SourceLocation.js';
|
||||||
|
export { Navigation, Meaning } from './items/ApiItem.js';
|
||||||
225
packages/api-extractor-model/src/items/ApiDeclaredItem.ts
Normal file
225
packages/api-extractor-model/src/items/ApiDeclaredItem.ts
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
// 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 { Excerpt, ExcerptToken, type IExcerptTokenRange, type IExcerptToken } from '../mixins/Excerpt.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import { SourceLocation } from '../model/SourceLocation.js';
|
||||||
|
import { ApiDocumentedItem, type IApiDocumentedItemJson, type IApiDocumentedItemOptions } from './ApiDocumentedItem.js';
|
||||||
|
import type { ApiItem } from './ApiItem.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link ApiDeclaredItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiDeclaredItemOptions extends IApiDocumentedItemOptions {
|
||||||
|
excerptTokens: IExcerptToken[];
|
||||||
|
fileColumn?: number | undefined;
|
||||||
|
fileLine?: number | undefined;
|
||||||
|
fileUrlPath?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiDeclaredItemJson extends IApiDocumentedItemJson {
|
||||||
|
excerptTokens: IExcerptToken[];
|
||||||
|
fileColumn?: number;
|
||||||
|
fileLine?: number;
|
||||||
|
fileUrlPath?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for API items that have an associated source code excerpt containing a TypeScript declaration.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations.
|
||||||
|
*
|
||||||
|
* Most `ApiItem` subclasses have declarations and thus extend `ApiDeclaredItem`. Counterexamples include
|
||||||
|
* `ApiModel` and `ApiPackage`, which do not have any corresponding TypeScript source code.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class ApiDeclaredItem extends ApiDocumentedItem {
|
||||||
|
private readonly _excerptTokens: ExcerptToken[];
|
||||||
|
|
||||||
|
private readonly _excerpt: Excerpt;
|
||||||
|
|
||||||
|
private readonly _fileUrlPath?: string | undefined;
|
||||||
|
|
||||||
|
private readonly _fileLine?: number | undefined;
|
||||||
|
|
||||||
|
private readonly _fileColumn?: number | undefined;
|
||||||
|
|
||||||
|
private _sourceLocation?: SourceLocation;
|
||||||
|
|
||||||
|
public constructor(options: IApiDeclaredItemOptions) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this._excerptTokens = options.excerptTokens.map((token) => {
|
||||||
|
const canonicalReference: DeclarationReference | undefined =
|
||||||
|
token.canonicalReference === undefined ? undefined : DeclarationReference.parse(token.canonicalReference);
|
||||||
|
return new ExcerptToken(token.kind, token.text, canonicalReference);
|
||||||
|
});
|
||||||
|
this._excerpt = new Excerpt(this.excerptTokens, { startIndex: 0, endIndex: this.excerptTokens.length });
|
||||||
|
this._fileUrlPath = options.fileUrlPath;
|
||||||
|
this._fileLine = options.fileLine;
|
||||||
|
this._fileColumn = options.fileColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiDeclaredItemOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiDeclaredItemJson,
|
||||||
|
): void {
|
||||||
|
super.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.excerptTokens = jsonObject.excerptTokens;
|
||||||
|
options.fileUrlPath = jsonObject.fileUrlPath;
|
||||||
|
options.fileLine = jsonObject.fileLine;
|
||||||
|
options.fileColumn = jsonObject.fileColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source code excerpt where the API item is declared.
|
||||||
|
*/
|
||||||
|
public get excerpt(): Excerpt {
|
||||||
|
return this._excerpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The individual source code tokens that comprise the main excerpt.
|
||||||
|
*/
|
||||||
|
public get excerptTokens(): readonly ExcerptToken[] {
|
||||||
|
return this._excerptTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file URL path relative to the `projectFolder` and `projectFolderURL` fields
|
||||||
|
* as defined in the `api-extractor.json` config. Is `undefined` if the path is
|
||||||
|
* the same as the parent API item's.
|
||||||
|
*/
|
||||||
|
public get fileUrlPath(): string | undefined {
|
||||||
|
return this._fileUrlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the source location where the API item is declared.
|
||||||
|
*/
|
||||||
|
public get sourceLocation(): SourceLocation {
|
||||||
|
if (!this._sourceLocation) {
|
||||||
|
this._sourceLocation = this._buildSourceLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._sourceLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the API item has certain important modifier tags such as `@sealed`, `@virtual`, or `@override`,
|
||||||
|
* this prepends them as a doc comment above the excerpt.
|
||||||
|
*/
|
||||||
|
public getExcerptWithModifiers(): string {
|
||||||
|
const excerpt: string = this.excerpt.text;
|
||||||
|
const modifierTags: string[] = [];
|
||||||
|
|
||||||
|
if (excerpt.length > 0 && this instanceof ApiDocumentedItem) {
|
||||||
|
if (this.tsdocComment) {
|
||||||
|
if (this.tsdocComment.modifierTagSet.isSealed()) {
|
||||||
|
modifierTags.push('@sealed');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tsdocComment.modifierTagSet.isVirtual()) {
|
||||||
|
modifierTags.push('@virtual');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tsdocComment.modifierTagSet.isOverride()) {
|
||||||
|
modifierTags.push('@override');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifierTags.length > 0) {
|
||||||
|
return '/** ' + modifierTags.join(' ') + ' */\n' + excerpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return excerpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiDeclaredItemJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
jsonObject.excerptTokens = this.excerptTokens.map((x) => {
|
||||||
|
const excerptToken: IExcerptToken = { kind: x.kind, text: x.text };
|
||||||
|
if (x.canonicalReference !== undefined) {
|
||||||
|
excerptToken.canonicalReference = x.canonicalReference.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return excerptToken;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only serialize this API item's file URL path if it exists and it's different from its parent's
|
||||||
|
// (a little optimization to keep the doc model succinct).
|
||||||
|
if (
|
||||||
|
this.fileUrlPath &&
|
||||||
|
(!(this.parent instanceof ApiDeclaredItem) || this.fileUrlPath !== this.parent.fileUrlPath)
|
||||||
|
) {
|
||||||
|
jsonObject.fileUrlPath = this.fileUrlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fileLine) {
|
||||||
|
jsonObject.fileLine = this.fileLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fileColumn) {
|
||||||
|
jsonObject.fileColumn = this.fileColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link Excerpt} corresponding to the provided token range.
|
||||||
|
*/
|
||||||
|
public buildExcerpt(tokenRange: IExcerptTokenRange): Excerpt {
|
||||||
|
return new Excerpt(this.excerptTokens, tokenRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the cached object used by the `sourceLocation` property.
|
||||||
|
*/
|
||||||
|
private _buildSourceLocation(): SourceLocation {
|
||||||
|
const projectFolderUrl: string | undefined = this.getAssociatedPackage()?.projectFolderUrl;
|
||||||
|
|
||||||
|
let fileUrlPath: string | undefined;
|
||||||
|
for (let current: ApiItem | undefined = this; current !== undefined; current = current.parent) {
|
||||||
|
if (current instanceof ApiDeclaredItem && current.fileUrlPath) {
|
||||||
|
fileUrlPath = current.fileUrlPath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceLocation({
|
||||||
|
projectFolderUrl,
|
||||||
|
fileUrlPath,
|
||||||
|
sourceFileColumn: this.fileColumn,
|
||||||
|
sourceFileLine: this.fileLine,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
78
packages/api-extractor-model/src/items/ApiDocumentedItem.ts
Normal file
78
packages/api-extractor-model/src/items/ApiDocumentedItem.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import * as tsdoc from '@microsoft/tsdoc';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import { ApiItem, type IApiItemOptions, type IApiItemJson } from './ApiItem.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link ApiDocumentedItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiDocumentedItemOptions extends IApiItemOptions {
|
||||||
|
docComment: tsdoc.DocComment | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiDocumentedItemJson extends IApiItemJson {
|
||||||
|
docComment: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract base class for API declarations that can have an associated TSDoc comment.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class ApiDocumentedItem extends ApiItem {
|
||||||
|
private readonly _tsdocComment: tsdoc.DocComment | undefined;
|
||||||
|
|
||||||
|
public constructor(options: IApiDocumentedItemOptions) {
|
||||||
|
super(options);
|
||||||
|
this._tsdocComment = options.docComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiDocumentedItemOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiItemJson,
|
||||||
|
): void {
|
||||||
|
super.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
const documentedJson: IApiDocumentedItemJson = jsonObject as IApiDocumentedItemJson;
|
||||||
|
|
||||||
|
if (documentedJson.docComment) {
|
||||||
|
const tsdocParser: tsdoc.TSDocParser = new tsdoc.TSDocParser(context.tsdocConfiguration);
|
||||||
|
|
||||||
|
// NOTE: For now, we ignore TSDoc errors found in a serialized .api.json file.
|
||||||
|
// Normally these errors would have already been reported by API Extractor during analysis.
|
||||||
|
// However, they could also arise if the JSON file was edited manually, or if the file was saved
|
||||||
|
// using a different release of the software that used an incompatible syntax.
|
||||||
|
const parserContext: tsdoc.ParserContext = tsdocParser.parseString(documentedJson.docComment);
|
||||||
|
|
||||||
|
options.docComment = parserContext.docComment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get tsdocComment(): tsdoc.DocComment | undefined {
|
||||||
|
return this._tsdocComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiDocumentedItemJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
if (this.tsdocComment === undefined) {
|
||||||
|
jsonObject.docComment = '';
|
||||||
|
} else {
|
||||||
|
jsonObject.docComment = this.tsdocComment.emitAsTsdoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
367
packages/api-extractor-model/src/items/ApiItem.ts
Normal file
367
packages/api-extractor-model/src/items/ApiItem.ts
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import { ApiItemContainerMixin } from '../mixins/ApiItemContainerMixin.js';
|
||||||
|
import { ApiParameterListMixin } from '../mixins/ApiParameterListMixin.js';
|
||||||
|
import type { Constructor, PropertiesOf } from '../mixins/Mixin.js';
|
||||||
|
import type { ApiModel } from '../model/ApiModel.js';
|
||||||
|
import type { ApiPackage } from '../model/ApiPackage.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type returned by the {@link ApiItem.kind} property, which can be used to easily distinguish subclasses of
|
||||||
|
* {@link ApiItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export enum ApiItemKind {
|
||||||
|
CallSignature = 'CallSignature',
|
||||||
|
Class = 'Class',
|
||||||
|
ConstructSignature = 'ConstructSignature',
|
||||||
|
Constructor = 'Constructor',
|
||||||
|
EntryPoint = 'EntryPoint',
|
||||||
|
Enum = 'Enum',
|
||||||
|
EnumMember = 'EnumMember',
|
||||||
|
Function = 'Function',
|
||||||
|
IndexSignature = 'IndexSignature',
|
||||||
|
Interface = 'Interface',
|
||||||
|
Method = 'Method',
|
||||||
|
MethodSignature = 'MethodSignature',
|
||||||
|
Model = 'Model',
|
||||||
|
Namespace = 'Namespace',
|
||||||
|
None = 'None',
|
||||||
|
Package = 'Package',
|
||||||
|
Property = 'Property',
|
||||||
|
PropertySignature = 'PropertySignature',
|
||||||
|
TypeAlias = 'TypeAlias',
|
||||||
|
Variable = 'Variable',
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Indicates the symbol table from which to resolve the next symbol component.
|
||||||
|
*
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
export enum Navigation {
|
||||||
|
Exports = '.',
|
||||||
|
Locals = '~',
|
||||||
|
Members = '#',
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
export enum Meaning {
|
||||||
|
CallSignature = 'call',
|
||||||
|
Class = 'class',
|
||||||
|
ComplexType = 'complex',
|
||||||
|
ConstructSignature = 'new',
|
||||||
|
Constructor = 'constructor',
|
||||||
|
Enum = 'enum',
|
||||||
|
Event = 'event',
|
||||||
|
Function = 'function',
|
||||||
|
IndexSignature = 'index',
|
||||||
|
Interface = 'interface',
|
||||||
|
Member = 'member',
|
||||||
|
Namespace = 'namespace',
|
||||||
|
TypeAlias = 'type',
|
||||||
|
Variable = 'var',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link ApiItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface IApiItemOptions {}
|
||||||
|
|
||||||
|
export interface IApiItemJson {
|
||||||
|
canonicalReference: string;
|
||||||
|
kind: ApiItemKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE - Allows ApiItemContainerMixin to assign the parent.
|
||||||
|
//
|
||||||
|
export const apiItem_onParentChanged: unique symbol = Symbol('ApiItem._onAddToContainer');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The abstract base class for all members of an `ApiModel` object.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class ApiItem {
|
||||||
|
private _canonicalReference: DeclarationReference | undefined;
|
||||||
|
|
||||||
|
private _parent: ApiItem | undefined;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
public constructor(_options: IApiItemOptions) {
|
||||||
|
// ("options" is not used here, but part of the inheritance pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static deserialize(jsonObject: IApiItemJson, context: DeserializerContext): ApiItem {
|
||||||
|
// The Deserializer class is coupled with a ton of other classes, so we delay loading it
|
||||||
|
// to avoid ES5 circular imports.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
||||||
|
const deserializerModule: typeof import('../model/Deserializer') = require('../model/Deserializer');
|
||||||
|
return deserializerModule.Deserializer.deserialize(context, jsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public static onDeserializeInto(
|
||||||
|
_options: Partial<IApiItemOptions>,
|
||||||
|
_context: DeserializerContext,
|
||||||
|
_jsonObject: IApiItemJson,
|
||||||
|
): void {
|
||||||
|
// (implemented by subclasses)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public serializeInto(jsonObject: Partial<IApiItemJson>): void {
|
||||||
|
jsonObject.kind = this.kind;
|
||||||
|
jsonObject.canonicalReference = this.canonicalReference.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies the subclass of the `ApiItem` base class.
|
||||||
|
*
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public get kind(): ApiItemKind {
|
||||||
|
throw new Error('ApiItem.kind was not implemented by the child class');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning: This API is used internally by API extractor but is not yet ready for general usage.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* Returns a `DeclarationReference` object using the experimental new declaration reference notation.
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
public get canonicalReference(): DeclarationReference {
|
||||||
|
if (!this._canonicalReference) {
|
||||||
|
try {
|
||||||
|
this._canonicalReference = this.buildCanonicalReference();
|
||||||
|
} catch (error) {
|
||||||
|
const name: string = this.getScopedNameWithinPackage() || this.displayName;
|
||||||
|
throw new InternalError(`Error building canonical reference for ${name}:\n` + (error as Error).message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._canonicalReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string key that can be used to efficiently retrieve an `ApiItem` from an `ApiItemContainerMixin`.
|
||||||
|
* The key is unique within the container. Its format is undocumented and may change at any time.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Use the `getContainerKey()` static member to construct the key. Each subclass has a different implementation
|
||||||
|
* of this function, according to the aspects that are important for identifying it.
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public get containerKey(): string {
|
||||||
|
throw new InternalError('ApiItem.containerKey was not implemented by the child class');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a name for this object that can be used in diagnostic messages, for example.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* For an object that inherits ApiNameMixin, this will return the declared name (e.g. the name of a TypeScript
|
||||||
|
* function). Otherwise, it will return a string such as "(call signature)" or "(model)".
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public get displayName(): string {
|
||||||
|
switch (this.kind) {
|
||||||
|
case ApiItemKind.CallSignature:
|
||||||
|
return '(call)';
|
||||||
|
case ApiItemKind.Constructor:
|
||||||
|
return '(constructor)';
|
||||||
|
case ApiItemKind.ConstructSignature:
|
||||||
|
return '(new)';
|
||||||
|
case ApiItemKind.IndexSignature:
|
||||||
|
return '(indexer)';
|
||||||
|
case ApiItemKind.Model:
|
||||||
|
return '(model)';
|
||||||
|
default:
|
||||||
|
return '(???)'; // All other types should inherit ApiNameMixin which will override this property
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this item was added to a ApiItemContainerMixin item, then this returns the container item.
|
||||||
|
* If this is an Parameter that was added to a method or function, then this returns the function item.
|
||||||
|
* Otherwise, it returns undefined.
|
||||||
|
*
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public get parent(): ApiItem | undefined {
|
||||||
|
return this._parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This property supports a visitor pattern for walking the tree.
|
||||||
|
* For items with ApiItemContainerMixin, it returns the contained items, sorted alphabetically.
|
||||||
|
* Otherwise it returns an empty array.
|
||||||
|
*
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public get members(): readonly ApiItem[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this item has a name (i.e. extends `ApiNameMixin`), then return all items that have the same parent
|
||||||
|
* and the same name. Otherwise, return all items that have the same parent and the same `ApiItemKind`.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Examples: For a function, this would return all overloads for the function. For a constructor, this would
|
||||||
|
* return all overloads for the constructor. For a merged declaration (e.g. a `namespace` and `enum` with the
|
||||||
|
* same name), this would return both declarations. If this item does not have a parent, or if it is the only
|
||||||
|
* item of its name/kind, then the result is an array containing only this item.
|
||||||
|
*/
|
||||||
|
public getMergedSiblings(): readonly ApiItem[] {
|
||||||
|
const parent: ApiItem | undefined = this._parent;
|
||||||
|
if (parent && ApiItemContainerMixin.isBaseClassOf(parent)) {
|
||||||
|
return parent._getMergedSiblingsForMember(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the chain of ancestors, starting from the root of the tree, and ending with the this item.
|
||||||
|
*/
|
||||||
|
public getHierarchy(): readonly ApiItem[] {
|
||||||
|
const hierarchy: ApiItem[] = [];
|
||||||
|
for (let current: ApiItem | undefined = this; current !== undefined; current = current.parent) {
|
||||||
|
hierarchy.push(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
hierarchy.reverse();
|
||||||
|
return hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This returns a scoped name such as `"Namespace1.Namespace2.MyClass.myMember()"`. It does not include the
|
||||||
|
* package name or entry point.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* If called on an ApiEntrypoint, ApiPackage, or ApiModel item, the result is an empty string.
|
||||||
|
*/
|
||||||
|
public getScopedNameWithinPackage(): string {
|
||||||
|
const reversedParts: string[] = [];
|
||||||
|
|
||||||
|
for (let current: ApiItem | undefined = this; current !== undefined; current = current.parent) {
|
||||||
|
if (
|
||||||
|
current.kind === ApiItemKind.Model ||
|
||||||
|
current.kind === ApiItemKind.Package ||
|
||||||
|
current.kind === ApiItemKind.EntryPoint
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reversedParts.length === 0) {
|
||||||
|
switch (current.kind) {
|
||||||
|
case ApiItemKind.CallSignature:
|
||||||
|
case ApiItemKind.ConstructSignature:
|
||||||
|
case ApiItemKind.Constructor:
|
||||||
|
case ApiItemKind.IndexSignature:
|
||||||
|
// These functional forms don't have a proper name, so we don't append the "()" suffix
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (ApiParameterListMixin.isBaseClassOf(current)) {
|
||||||
|
reversedParts.push('()');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reversedParts.push('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
reversedParts.push(current.displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reversedParts.reverse().join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this item is an ApiPackage or has an ApiPackage as one of its parents, then that object is returned.
|
||||||
|
* Otherwise undefined is returned.
|
||||||
|
*/
|
||||||
|
public getAssociatedPackage(): ApiPackage | undefined {
|
||||||
|
for (let current: ApiItem | undefined = this; current !== undefined; current = current.parent) {
|
||||||
|
if (current.kind === ApiItemKind.Package) {
|
||||||
|
return current as ApiPackage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this item is an ApiModel or has an ApiModel as one of its parents, then that object is returned.
|
||||||
|
* Otherwise undefined is returned.
|
||||||
|
*/
|
||||||
|
public getAssociatedModel(): ApiModel | undefined {
|
||||||
|
for (let current: ApiItem | undefined = this; current !== undefined; current = current.parent) {
|
||||||
|
if (current.kind === ApiItemKind.Model) {
|
||||||
|
return current as ApiModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A text string whose value determines the sort order that is automatically applied by the
|
||||||
|
* {@link (ApiItemContainerMixin:interface)} class.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* The value of this string is undocumented and may change at any time.
|
||||||
|
* If {@link (ApiItemContainerMixin:interface).preserveMemberOrder} is enabled for the `ApiItem`'s parent,
|
||||||
|
* then no sorting is performed, and this key is not used.
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
public getSortKey(): string {
|
||||||
|
return this.containerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PRIVATE
|
||||||
|
*
|
||||||
|
* @privateRemarks
|
||||||
|
* Allows ApiItemContainerMixin to assign the parent when the item is added to a container.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public [apiItem_onParentChanged](parent: ApiItem | undefined): void {
|
||||||
|
this._parent = parent;
|
||||||
|
this._canonicalReference = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the cached object used by the `canonicalReference` property.
|
||||||
|
*
|
||||||
|
* @virtual
|
||||||
|
*/
|
||||||
|
protected buildCanonicalReference(): DeclarationReference {
|
||||||
|
throw new InternalError('ApiItem.canonicalReference was not implemented by the child class');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstraction is used by the mixin pattern.
|
||||||
|
* It describes a class type that inherits from {@link ApiItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiItemConstructor extends Constructor<ApiItem>, PropertiesOf<typeof ApiItem> {}
|
||||||
88
packages/api-extractor-model/src/items/ApiPropertyItem.ts
Normal file
88
packages/api-extractor-model/src/items/ApiPropertyItem.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { type IApiNameMixinOptions, ApiNameMixin } from '../mixins/ApiNameMixin.js';
|
||||||
|
import { ApiOptionalMixin, type IApiOptionalMixinOptions } from '../mixins/ApiOptionalMixin.js';
|
||||||
|
import { ApiReadonlyMixin, type IApiReadonlyMixinOptions } from '../mixins/ApiReadonlyMixin.js';
|
||||||
|
import { ApiReleaseTagMixin, type IApiReleaseTagMixinOptions } from '../mixins/ApiReleaseTagMixin.js';
|
||||||
|
import type { Excerpt, IExcerptTokenRange } from '../mixins/Excerpt.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import { type IApiDeclaredItemOptions, ApiDeclaredItem, type IApiDeclaredItemJson } from './ApiDeclaredItem.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link ApiPropertyItem}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiPropertyItemOptions
|
||||||
|
extends IApiNameMixinOptions,
|
||||||
|
IApiReleaseTagMixinOptions,
|
||||||
|
IApiOptionalMixinOptions,
|
||||||
|
IApiReadonlyMixinOptions,
|
||||||
|
IApiDeclaredItemOptions {
|
||||||
|
propertyTypeTokenRange: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiPropertyItemJson extends IApiDeclaredItemJson {
|
||||||
|
propertyTypeTokenRange: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The abstract base class for {@link ApiProperty} and {@link ApiPropertySignature}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class ApiPropertyItem extends ApiNameMixin(
|
||||||
|
ApiReleaseTagMixin(ApiOptionalMixin(ApiReadonlyMixin(ApiDeclaredItem))),
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* An {@link Excerpt} that describes the type of the property.
|
||||||
|
*/
|
||||||
|
public readonly propertyTypeExcerpt: Excerpt;
|
||||||
|
|
||||||
|
public constructor(options: IApiPropertyItemOptions) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
this.propertyTypeExcerpt = this.buildExcerpt(options.propertyTypeTokenRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiPropertyItemOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiPropertyItemJson,
|
||||||
|
): void {
|
||||||
|
super.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.propertyTypeTokenRange = jsonObject.propertyTypeTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this property should be documented as an event.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* The `@eventProperty` TSDoc modifier can be added to readonly properties to indicate that they return an
|
||||||
|
* event object that event handlers can be attached to. The event-handling API is implementation-defined, but
|
||||||
|
* typically the return type would be a class with members such as `addHandler()` and `removeHandler()`.
|
||||||
|
* The documentation should display such properties under an "Events" heading instead of the
|
||||||
|
* usual "Properties" heading.
|
||||||
|
*/
|
||||||
|
public get isEventProperty(): boolean {
|
||||||
|
if (this.tsdocComment) {
|
||||||
|
return this.tsdocComment.modifierTagSet.isEventProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiPropertyItemJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.propertyTypeTokenRange = this.propertyTypeExcerpt.tokenRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
115
packages/api-extractor-model/src/mixins/ApiAbstractMixin.ts
Normal file
115
packages/api-extractor-model/src/mixins/ApiAbstractMixin.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiAbstractMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiAbstractMixinOptions extends IApiItemOptions {
|
||||||
|
isAbstract: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiAbstractMixinJson extends IApiItemJson {
|
||||||
|
isAbstract: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isAbstract: unique symbol = Symbol('ApiAbstractMixin._isAbstract');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that have an abstract modifier.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiAbstractMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* Indicates that the API item's value has an 'abstract' modifier.
|
||||||
|
*/
|
||||||
|
readonly isAbstract: boolean;
|
||||||
|
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiAbstractMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiAbstractMixin:interface)}
|
||||||
|
* functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiAbstractMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiAbstractMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiAbstractMixin {
|
||||||
|
public [_isAbstract]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiAbstractMixinOptions = args[0];
|
||||||
|
this[_isAbstract] = options.isAbstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiAbstractMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiAbstractMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.isAbstract = jsonObject.isAbstract || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isAbstract(): boolean {
|
||||||
|
return this[_isAbstract];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiAbstractMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.isAbstract = this.isAbstract;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiAbstractMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiAbstractMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiAbstractMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiAbstractMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isAbstract);
|
||||||
|
}
|
||||||
|
}
|
||||||
143
packages/api-extractor-model/src/mixins/ApiExportedMixin.ts
Normal file
143
packages/api-extractor-model/src/mixins/ApiExportedMixin.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 } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import { Navigation } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiExportedMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiExportedMixinOptions extends IApiItemOptions {
|
||||||
|
isExported: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiExportedMixinJson extends IApiItemJson {
|
||||||
|
isExported: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isExported: unique symbol = Symbol('ApiExportedMixin._isExported');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can be exported.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiExportedMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* Whether the declaration is exported from its parent item container (i.e. either an `ApiEntryPoint` or an
|
||||||
|
* `ApiNamespace`).
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Suppose `index.ts` is your entry point:
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* // index.ts
|
||||||
|
*
|
||||||
|
* export class A {}
|
||||||
|
* class B {}
|
||||||
|
*
|
||||||
|
* namespace n {
|
||||||
|
* export class C {}
|
||||||
|
* class D {}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // file.ts
|
||||||
|
* export class E {}
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Classes `A` and `C` are both exported, while classes `B`, `D`, and `E` are not. `E` is exported from its
|
||||||
|
* local file, but not from its parent item container (i.e. the entry point).
|
||||||
|
*/
|
||||||
|
readonly isExported: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiExportedMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiExportedMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiExportedMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiExportedMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiExportedMixin {
|
||||||
|
public [_isExported]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiExportedMixinOptions = args[0];
|
||||||
|
this[_isExported] = options.isExported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiExportedMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiExportedMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
const declarationReference: DeclarationReference = DeclarationReference.parse(jsonObject.canonicalReference);
|
||||||
|
options.isExported = declarationReference.navigation === (Navigation.Exports as any); // ambient const enums suck...
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isExported(): boolean {
|
||||||
|
return this[_isExported];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `isExported` property is intentionally not serialized because the information is already present
|
||||||
|
* in the item's `canonicalReference`.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiExportedMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiExportedMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiExportedMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiExportedMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiExportedMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isExported);
|
||||||
|
}
|
||||||
|
}
|
||||||
130
packages/api-extractor-model/src/mixins/ApiInitializerMixin.ts
Normal file
130
packages/api-extractor-model/src/mixins/ApiInitializerMixin.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import { ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import type { IExcerptTokenRange, Excerpt } from './Excerpt.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiInitializerMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiInitializerMixinOptions extends IApiItemOptions {
|
||||||
|
initializerTokenRange?: IExcerptTokenRange | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiInitializerMixinJson extends IApiItemJson {
|
||||||
|
initializerTokenRange?: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _initializerExcerpt: unique symbol = Symbol('ApiInitializerMixin._initializerExcerpt');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can have an initializer.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiInitializerMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* An {@link Excerpt} that describes the item's initializer.
|
||||||
|
*/
|
||||||
|
readonly initializerExcerpt?: Excerpt | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiInitializerMixinJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiInitializerMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiInitializerMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiInitializerMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiInitializerMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiInitializerMixin {
|
||||||
|
public [_initializerExcerpt]?: Excerpt;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiInitializerMixinOptions = args[0];
|
||||||
|
|
||||||
|
if (this instanceof ApiDeclaredItem) {
|
||||||
|
if (options.initializerTokenRange) {
|
||||||
|
this[_initializerExcerpt] = this.buildExcerpt(options.initializerTokenRange);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InternalError('ApiInitializerMixin expects a base class that inherits from ApiDeclaredItem');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiInitializerMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiInitializerMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.initializerTokenRange = jsonObject.initializerTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get initializerExcerpt(): Excerpt | undefined {
|
||||||
|
return this[_initializerExcerpt];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiInitializerMixinJson>): 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.initializerExcerpt) {
|
||||||
|
jsonObject.initializerTokenRange = this.initializerExcerpt.tokenRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiInitializerMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiInitializerMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiInitializerMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiInitializerMixin {
|
||||||
|
return apiItem.hasOwnProperty(_initializerExcerpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
562
packages/api-extractor-model/src/mixins/ApiItemContainerMixin.ts
Normal file
562
packages/api-extractor-model/src/mixins/ApiItemContainerMixin.ts
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import {
|
||||||
|
ApiItem,
|
||||||
|
apiItem_onParentChanged,
|
||||||
|
type IApiItemJson,
|
||||||
|
type IApiItemOptions,
|
||||||
|
type IApiItemConstructor,
|
||||||
|
ApiItemKind,
|
||||||
|
} from '../items/ApiItem.js';
|
||||||
|
import type { ApiClass } from '../model/ApiClass.js';
|
||||||
|
import type { ApiInterface } from '../model/ApiInterface.js';
|
||||||
|
import type { ApiModel } from '../model/ApiModel.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import type { HeritageType } from '../model/HeritageType.js';
|
||||||
|
import type { IResolveDeclarationReferenceResult } from '../model/ModelReferenceResolver.js';
|
||||||
|
import { ApiNameMixin } from './ApiNameMixin.js';
|
||||||
|
import { type ExcerptToken, ExcerptTokenKind } from './Excerpt.js';
|
||||||
|
import { type IFindApiItemsResult, type IFindApiItemsMessage, FindApiItemsMessageId } from './IFindApiItemsResult.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiItemContainerMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiItemContainerMixinOptions extends IApiItemOptions {
|
||||||
|
members?: ApiItem[] | undefined;
|
||||||
|
preserveMemberOrder?: boolean | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiItemContainerJson extends IApiItemJson {
|
||||||
|
members: IApiItemJson[];
|
||||||
|
preserveMemberOrder?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _members: unique symbol = Symbol('ApiItemContainerMixin._members');
|
||||||
|
const _membersSorted: unique symbol = Symbol('ApiItemContainerMixin._membersSorted');
|
||||||
|
const _membersByContainerKey: unique symbol = Symbol('ApiItemContainerMixin._membersByContainerKey');
|
||||||
|
const _membersByName: unique symbol = Symbol('ApiItemContainerMixin._membersByName');
|
||||||
|
const _membersByKind: unique symbol = Symbol('ApiItemContainerMixin._membersByKind');
|
||||||
|
const _preserveMemberOrder: unique symbol = Symbol('ApiItemContainerMixin._preserveMemberOrder');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that act as containers for other child items.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
*
|
||||||
|
* Examples of `ApiItemContainerMixin` child classes include `ApiModel`, `ApiPackage`, `ApiEntryPoint`,
|
||||||
|
* and `ApiEnum`. But note that `Parameter` is not considered a "member" of an `ApiMethod`; this relationship
|
||||||
|
* is modeled using {@link (ApiParameterListMixin:interface).parameters} instead
|
||||||
|
* of {@link ApiItem.members}.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiItemContainerMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* For a given member of this container, return its `ApiItem.getMergedSiblings()` list.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
_getMergedSiblingsForMember(memberApiItem: ApiItem): readonly ApiItem[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new member to the container.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* An ApiItem cannot be added to more than one container.
|
||||||
|
*/
|
||||||
|
addMember(member: ApiItem): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of members with the specified name.
|
||||||
|
*/
|
||||||
|
findMembersByName(name: string): readonly ApiItem[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all of the ApiItem's immediate and inherited members by walking up the inheritance tree.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* Given the following class heritage:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* export class A {
|
||||||
|
* public a: number|boolean;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* export class B extends A {
|
||||||
|
* public a: number;
|
||||||
|
* public b: string;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* export class C extends B {
|
||||||
|
* public c: boolean;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Calling `findMembersWithInheritance` on `C` will return `B.a`, `B.b`, and `C.c`. Calling the
|
||||||
|
* method on `B` will return `B.a` and `B.b`. And calling the method on `A` will return just
|
||||||
|
* `A.a`.
|
||||||
|
*
|
||||||
|
* The inherited members returned by this method may be incomplete. If so, there will be a flag
|
||||||
|
* on the result object indicating this as well as messages explaining the errors in more detail.
|
||||||
|
* Some scenarios include:
|
||||||
|
*
|
||||||
|
* - Interface extending from a type alias.
|
||||||
|
*
|
||||||
|
* - Class extending from a variable.
|
||||||
|
*
|
||||||
|
* - Extending from a declaration not present in the model (e.g. external package).
|
||||||
|
*
|
||||||
|
* - Extending from an unexported declaration (e.g. ae-forgotten-export). Common in mixin
|
||||||
|
* patterns.
|
||||||
|
*
|
||||||
|
* - Unexpected runtime errors...
|
||||||
|
*
|
||||||
|
* Lastly, be aware that the types of inherited members are returned with respect to their
|
||||||
|
* defining class as opposed to with respect to the inheriting class. For example, consider
|
||||||
|
* the following:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* export class A<T> {
|
||||||
|
* public a: T;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* export class B extends A<number> {}
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* When called on `B`, this method will return `B.a` with type `T` as opposed to type
|
||||||
|
* `number`, although the latter is more accurate.
|
||||||
|
*/
|
||||||
|
findMembersWithInheritance(): IFindApiItemsResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables automatic sorting of {@link ApiItem.members}.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* By default `ApiItemContainerMixin` will automatically sort its members according to their
|
||||||
|
* {@link ApiItem.getSortKey} string, which provides a standardized mostly alphabetical ordering
|
||||||
|
* that is appropriate for most API items. When loading older .api.json files the automatic sorting
|
||||||
|
* is reapplied and may update the ordering.
|
||||||
|
*
|
||||||
|
* Set `preserveMemberOrder` to true to disable automatic sorting for this container; instead, the
|
||||||
|
* members will retain whatever ordering appeared in the {@link IApiItemContainerMixinOptions.members} array.
|
||||||
|
* The `preserveMemberOrder` option is saved in the .api.json file.
|
||||||
|
*/
|
||||||
|
readonly preserveMemberOrder: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to retrieve a member using its containerKey, or returns `undefined` if no matching member was found.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Use the `getContainerKey()` static member to construct the key. Each subclass has a different implementation
|
||||||
|
* of this function, according to the aspects that are important for identifying it.
|
||||||
|
*
|
||||||
|
* See {@link ApiItem.containerKey} for more information.
|
||||||
|
*/
|
||||||
|
tryGetMemberByKey(containerKey: string): ApiItem | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link ApiDeclaredItem}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiItemContainerMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiItemContainerMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiItemContainerMixin {
|
||||||
|
public readonly [_members]: ApiItem[];
|
||||||
|
|
||||||
|
public [_membersSorted]: boolean;
|
||||||
|
|
||||||
|
public [_membersByContainerKey]: Map<string, ApiItem>;
|
||||||
|
|
||||||
|
public [_preserveMemberOrder]: boolean;
|
||||||
|
|
||||||
|
// For members of this container that extend ApiNameMixin, this stores the list of members with a given name.
|
||||||
|
// Examples include merged declarations, overloaded functions, etc.
|
||||||
|
public [_membersByName]: Map<string, ApiItem[]> | undefined;
|
||||||
|
|
||||||
|
// For members of this container that do NOT extend ApiNameMixin, this stores the list of members
|
||||||
|
// that share a common ApiItemKind. Examples include overloaded constructors or index signatures.
|
||||||
|
public [_membersByKind]: Map<string, ApiItem[]> | undefined; // key is ApiItemKind
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
const options: IApiItemContainerMixinOptions = args[0] as IApiItemContainerMixinOptions;
|
||||||
|
|
||||||
|
this[_members] = [];
|
||||||
|
this[_membersSorted] = false;
|
||||||
|
this[_membersByContainerKey] = new Map<string, ApiItem>();
|
||||||
|
this[_preserveMemberOrder] = options.preserveMemberOrder ?? false;
|
||||||
|
|
||||||
|
if (options.members) {
|
||||||
|
for (const member of options.members) {
|
||||||
|
this.addMember(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiItemContainerMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiItemContainerJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
options.preserveMemberOrder = jsonObject.preserveMemberOrder;
|
||||||
|
options.members = [];
|
||||||
|
for (const memberObject of jsonObject.members) {
|
||||||
|
options.members.push(ApiItem.deserialize(memberObject, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override get members(): readonly ApiItem[] {
|
||||||
|
if (!this[_membersSorted] && !this[_preserveMemberOrder]) {
|
||||||
|
this[_members].sort((x, y) => x.getSortKey().localeCompare(y.getSortKey()));
|
||||||
|
this[_membersSorted] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this[_members];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get preserveMemberOrder(): boolean {
|
||||||
|
return this[_preserveMemberOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
public addMember(member: ApiItem): void {
|
||||||
|
if (this[_membersByContainerKey].has(member.containerKey)) {
|
||||||
|
throw new Error(
|
||||||
|
`Another member has already been added with the same name (${member.displayName})` +
|
||||||
|
` and containerKey (${member.containerKey})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingParent: ApiItem | undefined = member.parent;
|
||||||
|
if (existingParent !== undefined) {
|
||||||
|
throw new Error(`This item has already been added to another container: "${existingParent.displayName}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this[_members].push(member);
|
||||||
|
this[_membersByName] = undefined; // invalidate the lookup
|
||||||
|
this[_membersByKind] = undefined; // invalidate the lookup
|
||||||
|
this[_membersSorted] = false;
|
||||||
|
this[_membersByContainerKey].set(member.containerKey, member);
|
||||||
|
|
||||||
|
member[apiItem_onParentChanged](this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public tryGetMemberByKey(containerKey: string): ApiItem | undefined {
|
||||||
|
return this[_membersByContainerKey].get(containerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public findMembersByName(name: string): readonly ApiItem[] {
|
||||||
|
this._ensureMemberMaps();
|
||||||
|
return this[_membersByName]!.get(name) ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public findMembersWithInheritance(): IFindApiItemsResult {
|
||||||
|
const messages: IFindApiItemsMessage[] = [];
|
||||||
|
let maybeIncompleteResult = false;
|
||||||
|
|
||||||
|
// For API items that don't support inheritance, this method just returns the item's
|
||||||
|
// immediate members.
|
||||||
|
switch (this.kind) {
|
||||||
|
case ApiItemKind.Class:
|
||||||
|
case ApiItemKind.Interface:
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
return {
|
||||||
|
items: this.members.concat(),
|
||||||
|
messages,
|
||||||
|
maybeIncompleteResult,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const membersByName: Map<string, ApiItem[]> = new Map();
|
||||||
|
const membersByKind: Map<ApiItemKind, ApiItem[]> = new Map();
|
||||||
|
|
||||||
|
const toVisit: ApiItem[] = [];
|
||||||
|
let next: ApiItem | undefined = this;
|
||||||
|
|
||||||
|
while (next) {
|
||||||
|
const membersToAdd: ApiItem[] = [];
|
||||||
|
|
||||||
|
// For each member, check to see if we've already seen a member with the same name
|
||||||
|
// previously in the inheritance tree. If so, we know we won't inherit it, and thus
|
||||||
|
// do not add it to our `membersToAdd` array.
|
||||||
|
for (const member of next.members) {
|
||||||
|
// We add the to-be-added members to an intermediate array instead of immediately
|
||||||
|
// to the maps themselves to support method overloads with the same name.
|
||||||
|
if (ApiNameMixin.isBaseClassOf(member)) {
|
||||||
|
if (!membersByName.has(member.name)) {
|
||||||
|
membersToAdd.push(member);
|
||||||
|
}
|
||||||
|
} else if (!membersByKind.has(member.kind)) {
|
||||||
|
membersToAdd.push(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const member of membersToAdd) {
|
||||||
|
if (ApiNameMixin.isBaseClassOf(member)) {
|
||||||
|
const members: ApiItem[] = membersByName.get(member.name) ?? [];
|
||||||
|
members.push(member);
|
||||||
|
membersByName.set(member.name, members);
|
||||||
|
} else {
|
||||||
|
const members: ApiItem[] = membersByKind.get(member.kind) ?? [];
|
||||||
|
members.push(member);
|
||||||
|
membersByKind.set(member.kind, members);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interfaces can extend multiple interfaces, so iterate through all of them.
|
||||||
|
const extendedItems: ApiItem[] = [];
|
||||||
|
let extendsTypes: readonly HeritageType[] | undefined;
|
||||||
|
|
||||||
|
switch (next.kind) {
|
||||||
|
case ApiItemKind.Class: {
|
||||||
|
const apiClass: ApiClass = next as ApiClass;
|
||||||
|
extendsTypes = apiClass.extendsType ? [apiClass.extendsType] : [];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ApiItemKind.Interface: {
|
||||||
|
const apiInterface: ApiInterface = next as ApiInterface;
|
||||||
|
extendsTypes = apiInterface.extendsTypes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extendsTypes === undefined) {
|
||||||
|
messages.push({
|
||||||
|
messageId: FindApiItemsMessageId.UnsupportedKind,
|
||||||
|
text: `Unable to analyze references of API item ${next.displayName} because it is of unsupported kind ${next.kind}`,
|
||||||
|
});
|
||||||
|
maybeIncompleteResult = true;
|
||||||
|
next = toVisit.shift();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const extendsType of extendsTypes) {
|
||||||
|
// We want to find the reference token associated with the actual inherited declaration.
|
||||||
|
// In every case we support, this is the first reference token. For example:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// export class A extends B {}
|
||||||
|
// ^
|
||||||
|
// export class A extends B<C> {}
|
||||||
|
// ^
|
||||||
|
// export class A extends B.C {}
|
||||||
|
// ^^^
|
||||||
|
// ```
|
||||||
|
const firstReferenceToken: ExcerptToken | undefined = extendsType.excerpt.spannedTokens.find(
|
||||||
|
(token: ExcerptToken) => {
|
||||||
|
return token.kind === ExcerptTokenKind.Reference && token.canonicalReference;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!firstReferenceToken) {
|
||||||
|
messages.push({
|
||||||
|
messageId: FindApiItemsMessageId.ExtendsClauseMissingReference,
|
||||||
|
text: `Unable to analyze extends clause ${extendsType.excerpt.text} of API item ${next.displayName} because no canonical reference was found`,
|
||||||
|
});
|
||||||
|
maybeIncompleteResult = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiModel: ApiModel | undefined = this.getAssociatedModel();
|
||||||
|
if (!apiModel) {
|
||||||
|
messages.push({
|
||||||
|
messageId: FindApiItemsMessageId.NoAssociatedApiModel,
|
||||||
|
text: `Unable to analyze references of API item ${next.displayName} because it is not associated with an ApiModel`,
|
||||||
|
});
|
||||||
|
maybeIncompleteResult = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const canonicalReference: DeclarationReference = firstReferenceToken.canonicalReference!;
|
||||||
|
const apiItemResult: IResolveDeclarationReferenceResult = apiModel.resolveDeclarationReference(
|
||||||
|
canonicalReference,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
|
const apiItem: ApiItem | undefined = apiItemResult.resolvedApiItem;
|
||||||
|
if (!apiItem) {
|
||||||
|
messages.push({
|
||||||
|
messageId: FindApiItemsMessageId.DeclarationResolutionFailed,
|
||||||
|
text: `Unable to resolve declaration reference within API item ${next.displayName}: ${apiItemResult.errorMessage}`,
|
||||||
|
});
|
||||||
|
maybeIncompleteResult = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
extendedItems.push(apiItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For classes, this array will only have one item. For interfaces, there may be multiple items. Sort the array
|
||||||
|
// into alphabetical order before adding to our list of API items to visit. This ensures that in the case
|
||||||
|
// of multiple interface inheritance, a member inherited from multiple interfaces is attributed to the interface
|
||||||
|
// earlier in alphabetical order (as opposed to source order).
|
||||||
|
//
|
||||||
|
// For example, in the code block below, `Bar.x` is reported as the inherited item, not `Foo.x`.
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// interface Foo {
|
||||||
|
// public x: string;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// interface Bar {
|
||||||
|
// public x: string;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// interface FooBar extends Foo, Bar {}
|
||||||
|
// ```
|
||||||
|
extendedItems.sort((x: ApiItem, y: ApiItem) => x.getSortKey().localeCompare(y.getSortKey()));
|
||||||
|
|
||||||
|
toVisit.push(...extendedItems);
|
||||||
|
next = toVisit.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
const items: ApiItem[] = [];
|
||||||
|
for (const members of membersByName.values()) {
|
||||||
|
items.push(...members);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const members of membersByKind.values()) {
|
||||||
|
items.push(...members);
|
||||||
|
}
|
||||||
|
|
||||||
|
items.sort((x: ApiItem, y: ApiItem) => x.getSortKey().localeCompare(y.getSortKey()));
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
messages,
|
||||||
|
maybeIncompleteResult,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public _getMergedSiblingsForMember(memberApiItem: ApiItem): readonly ApiItem[] {
|
||||||
|
this._ensureMemberMaps();
|
||||||
|
let result: ApiItem[] | undefined;
|
||||||
|
if (ApiNameMixin.isBaseClassOf(memberApiItem)) {
|
||||||
|
result = this[_membersByName]!.get(memberApiItem.name);
|
||||||
|
} else {
|
||||||
|
result = this[_membersByKind]!.get(memberApiItem.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
throw new InternalError('Item was not found in the _membersByName/_membersByKind lookup');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public _ensureMemberMaps(): void {
|
||||||
|
// Build the _membersByName and _membersByKind tables if they don't already exist
|
||||||
|
if (this[_membersByName] === undefined) {
|
||||||
|
const membersByName: Map<string, ApiItem[]> = new Map<string, ApiItem[]>();
|
||||||
|
const membersByKind: Map<string, ApiItem[]> = new Map<string, ApiItem[]>();
|
||||||
|
|
||||||
|
for (const member of this[_members]) {
|
||||||
|
let map: Map<ApiItemKind, ApiItem[]> | Map<string, ApiItem[]>;
|
||||||
|
let key: ApiItemKind | string;
|
||||||
|
|
||||||
|
if (ApiNameMixin.isBaseClassOf(member)) {
|
||||||
|
map = membersByName;
|
||||||
|
key = member.name;
|
||||||
|
} else {
|
||||||
|
map = membersByKind;
|
||||||
|
key = member.kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
let list: ApiItem[] | undefined = map.get(key);
|
||||||
|
if (list === undefined) {
|
||||||
|
list = [];
|
||||||
|
map.set(key, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.push(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
this[_membersByName] = membersByName;
|
||||||
|
this[_membersByKind] = membersByKind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiItemContainerJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
const memberObjects: IApiItemJson[] = [];
|
||||||
|
|
||||||
|
for (const member of this.members) {
|
||||||
|
const memberJsonObject: Partial<IApiItemJson> = {};
|
||||||
|
member.serializeInto(memberJsonObject);
|
||||||
|
memberObjects.push(memberJsonObject as IApiItemJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonObject.preserveMemberOrder = this.preserveMemberOrder;
|
||||||
|
jsonObject.members = memberObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiItemContainerMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export namespace ApiItemContainerMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiItemContainerMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiItemContainerMixin {
|
||||||
|
return apiItem.hasOwnProperty(_members);
|
||||||
|
}
|
||||||
|
}
|
||||||
128
packages/api-extractor-model/src/mixins/ApiNameMixin.ts
Normal file
128
packages/api-extractor-model/src/mixins/ApiNameMixin.ts
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiNameMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiNameMixinOptions extends IApiItemOptions {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiNameMixinJson extends IApiItemJson {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _name: unique symbol = Symbol('ApiNameMixin._name');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that have a name. For example, a class has a name, but a class constructor
|
||||||
|
* does not.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiNameMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* The exported name of this API item.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Note that due tue type aliasing, the exported name may be different from the locally declared name.
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiNameMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiNameMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiNameMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiNameMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiNameMixin {
|
||||||
|
public readonly [_name]: string;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiNameMixinOptions = args[0];
|
||||||
|
this[_name] = options.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiNameMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiNameMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.name = jsonObject.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name(): string {
|
||||||
|
return this[_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override get displayName(): string {
|
||||||
|
return this[_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiNameMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.name = this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiNameMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiNameMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiNameMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiNameMixin {
|
||||||
|
return apiItem.hasOwnProperty(_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
127
packages/api-extractor-model/src/mixins/ApiOptionalMixin.ts
Normal file
127
packages/api-extractor-model/src/mixins/ApiOptionalMixin.ts
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiOptionalMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiOptionalMixinOptions extends IApiItemOptions {
|
||||||
|
isOptional: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiOptionalMixinJson extends IApiItemJson {
|
||||||
|
isOptional: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isOptional: unique symbol = Symbol('ApiOptionalMixin._isOptional');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can be marked as optional by appending a `?` to them.
|
||||||
|
* For example, a property of an interface can be optional.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiOptionalMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* True if this is an optional property.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* For example:
|
||||||
|
* ```ts
|
||||||
|
* interface X {
|
||||||
|
* y: string; // not optional
|
||||||
|
* z?: string; // optional
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
readonly isOptional: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiOptionalMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiOptionalMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiOptionalMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiOptionalMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiOptionalMixin {
|
||||||
|
public [_isOptional]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiOptionalMixinOptions = args[0];
|
||||||
|
this[_isOptional] = Boolean(options.isOptional);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiOptionalMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiOptionalMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.isOptional = Boolean(jsonObject.isOptional);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isOptional(): boolean {
|
||||||
|
return this[_isOptional];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiOptionalMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.isOptional = this.isOptional;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional members for {@link (ApiOptionalMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiOptionalMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiOptionalMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiOptionalMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isOptional);
|
||||||
|
}
|
||||||
|
}
|
||||||
202
packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts
Normal file
202
packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import { ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import { Parameter } from '../model/Parameter.js';
|
||||||
|
import type { IExcerptTokenRange } from './Excerpt.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents parameter information that is part of {@link IApiParameterListMixinOptions}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiParameterOptions {
|
||||||
|
isOptional: boolean;
|
||||||
|
isRest: boolean;
|
||||||
|
parameterName: string;
|
||||||
|
parameterTypeTokenRange: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiParameterListMixinOptions extends IApiItemOptions {
|
||||||
|
overloadIndex: number;
|
||||||
|
parameters: IApiParameterOptions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiParameterListJson extends IApiItemJson {
|
||||||
|
overloadIndex: number;
|
||||||
|
parameters: IApiParameterOptions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const _overloadIndex: unique symbol = Symbol('ApiParameterListMixin._overloadIndex');
|
||||||
|
const _parameters: unique symbol = Symbol('ApiParameterListMixin._parameters');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can have function parameters (but not necessarily a return value).
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiParameterListMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* When a function has multiple overloaded declarations, this one-based integer index can be used to uniquely
|
||||||
|
* identify them.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* Consider this overloaded declaration:
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* export namespace Versioning {
|
||||||
|
* // TSDoc: Versioning.(addVersions:1)
|
||||||
|
* export function addVersions(x: number, y: number): number;
|
||||||
|
*
|
||||||
|
* // TSDoc: Versioning.(addVersions:2)
|
||||||
|
* export function addVersions(x: string, y: string): string;
|
||||||
|
*
|
||||||
|
* // (implementation)
|
||||||
|
* export function addVersions(x: number|string, y: number|string): number|string {
|
||||||
|
* // . . .
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In the above example, there are two overloaded declarations. The overload using numbers will have
|
||||||
|
* `overloadIndex = 1`. The overload using strings will have `overloadIndex = 2`. The third declaration that
|
||||||
|
* accepts all possible inputs is considered part of the implementation, and is not processed by API Extractor.
|
||||||
|
*/
|
||||||
|
readonly overloadIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function parameters.
|
||||||
|
*/
|
||||||
|
readonly parameters: readonly Parameter[];
|
||||||
|
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiParameterListMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiParameterListMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiParameterListMixin {
|
||||||
|
public readonly [_overloadIndex]: number;
|
||||||
|
|
||||||
|
public readonly [_parameters]: Parameter[];
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiParameterListMixinOptions = args[0];
|
||||||
|
this[_overloadIndex] = options.overloadIndex;
|
||||||
|
|
||||||
|
this[_parameters] = [];
|
||||||
|
|
||||||
|
if (this instanceof ApiDeclaredItem) {
|
||||||
|
if (options.parameters) {
|
||||||
|
for (const parameterOptions of options.parameters) {
|
||||||
|
const parameter: Parameter = new Parameter({
|
||||||
|
name: parameterOptions.parameterName,
|
||||||
|
parameterTypeExcerpt: this.buildExcerpt(parameterOptions.parameterTypeTokenRange),
|
||||||
|
// Prior to ApiJsonSchemaVersion.V_1005 this input will be undefined
|
||||||
|
isOptional: Boolean(parameterOptions.isOptional),
|
||||||
|
isRest: Boolean(parameterOptions.isRest),
|
||||||
|
parent: this,
|
||||||
|
});
|
||||||
|
|
||||||
|
this[_parameters].push(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InternalError('ApiReturnTypeMixin expects a base class that inherits from ApiDeclaredItem');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiParameterListMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiParameterListJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.overloadIndex = jsonObject.overloadIndex;
|
||||||
|
options.parameters = jsonObject.parameters || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get overloadIndex(): number {
|
||||||
|
return this[_overloadIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get parameters(): readonly Parameter[] {
|
||||||
|
return this[_parameters];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiParameterListJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.overloadIndex = this.overloadIndex;
|
||||||
|
|
||||||
|
const parameterObjects: IApiParameterOptions[] = [];
|
||||||
|
for (const parameter of this.parameters) {
|
||||||
|
parameterObjects.push({
|
||||||
|
parameterName: parameter.name,
|
||||||
|
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
|
||||||
|
isOptional: parameter.isOptional,
|
||||||
|
isRest: parameter.isRest,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonObject.parameters = parameterObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiParameterListMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiParameterListMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiParameterListMixin {
|
||||||
|
return apiItem.hasOwnProperty(_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
117
packages/api-extractor-model/src/mixins/ApiProtectedMixin.ts
Normal file
117
packages/api-extractor-model/src/mixins/ApiProtectedMixin.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiProtectedMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiProtectedMixinOptions extends IApiItemOptions {
|
||||||
|
isProtected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiProtectedMixinJson extends IApiItemJson {
|
||||||
|
isProtected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isProtected: unique symbol = Symbol('ApiProtectedMixin._isProtected');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can have the TypeScript `protected` keyword applied to them.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiProtectedMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* Whether the declaration has the TypeScript `protected` keyword.
|
||||||
|
*/
|
||||||
|
readonly isProtected: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiProtectedMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiProtectedMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiProtectedMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiProtectedMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiProtectedMixin {
|
||||||
|
public [_isProtected]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiProtectedMixinOptions = args[0];
|
||||||
|
this[_isProtected] = options.isProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiProtectedMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiProtectedMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.isProtected = jsonObject.isProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isProtected(): boolean {
|
||||||
|
return this[_isProtected];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiProtectedMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.isProtected = this.isProtected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiProtectedMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiProtectedMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiProtectedMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiProtectedMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isProtected);
|
||||||
|
}
|
||||||
|
}
|
||||||
137
packages/api-extractor-model/src/mixins/ApiReadonlyMixin.ts
Normal file
137
packages/api-extractor-model/src/mixins/ApiReadonlyMixin.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 type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiReadonlyMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiReadonlyMixinOptions extends IApiItemOptions {
|
||||||
|
isReadonly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiReadonlyMixinJson extends IApiItemJson {
|
||||||
|
isReadonly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isReadonly: unique symbol = Symbol('ApiReadonlyMixin._isReadonly');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that cannot be modified after instantiation.
|
||||||
|
* Examples such as the readonly modifier and only having a getter but no setter.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiReadonlyMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* Indicates that the API item's value cannot be assigned by an external consumer.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Examples of API items that would be considered "read only" by API Extractor:
|
||||||
|
*
|
||||||
|
* - A class or interface's property that has the `readonly` modifier.
|
||||||
|
*
|
||||||
|
* - A variable that has the `const` modifier.
|
||||||
|
*
|
||||||
|
* - A property or variable whose TSDoc comment includes the `@readonly` tag.
|
||||||
|
*
|
||||||
|
* - A property declaration with a getter but no setter.
|
||||||
|
*
|
||||||
|
* Note that if the `readonly` keyword appears in a type annotation, this does not
|
||||||
|
* guarantee that that the API item will be considered readonly. For example:
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* declare class C {
|
||||||
|
* // isReadonly=false in this case, because C.x is assignable
|
||||||
|
* public x: readonly string[];
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
readonly isReadonly: boolean;
|
||||||
|
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiReadonlyMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiReadonlyMixin:interface)}
|
||||||
|
* functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiReadonlyMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiReadonlyMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiReadonlyMixin {
|
||||||
|
public [_isReadonly]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiReadonlyMixinOptions = args[0];
|
||||||
|
this[_isReadonly] = options.isReadonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiReadonlyMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiReadonlyMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.isReadonly = jsonObject.isReadonly || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isReadonly(): boolean {
|
||||||
|
return this[_isReadonly];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiReadonlyMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.isReadonly = this.isReadonly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiReadonlyMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiReadonlyMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiReadonlyMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiReadonlyMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isReadonly);
|
||||||
|
}
|
||||||
|
}
|
||||||
132
packages/api-extractor-model/src/mixins/ApiReleaseTagMixin.ts
Normal file
132
packages/api-extractor-model/src/mixins/ApiReleaseTagMixin.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { Enum } from '@rushstack/node-core-library';
|
||||||
|
import { ReleaseTag } from '../aedoc/ReleaseTag.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiReleaseTagMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiReleaseTagMixinOptions extends IApiItemOptions {
|
||||||
|
releaseTag: ReleaseTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiReleaseTagMixinJson extends IApiItemJson {
|
||||||
|
releaseTag: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _releaseTag: unique symbol = Symbol('ApiReleaseTagMixin._releaseTag');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can be attributed with a TSDoc tag such as `@internal`,
|
||||||
|
* `@alpha`, `@beta`, or `@public`. These "release tags" indicate the support level for an API.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiReleaseTagMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* The effective release tag for this declaration. If it is not explicitly specified, the value may be
|
||||||
|
* inherited from a containing declaration.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* For example, an `ApiEnumMember` may inherit its release tag from the containing `ApiEnum`.
|
||||||
|
*/
|
||||||
|
readonly releaseTag: ReleaseTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiReleaseTagMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiReleaseTagMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiReleaseTagMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiReleaseTagMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiReleaseTagMixin {
|
||||||
|
public [_releaseTag]: ReleaseTag;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiReleaseTagMixinOptions = args[0];
|
||||||
|
this[_releaseTag] = options.releaseTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiReleaseTagMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiReleaseTagMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
const deserializedReleaseTag: ReleaseTag | undefined = Enum.tryGetValueByKey<ReleaseTag>(
|
||||||
|
ReleaseTag as any,
|
||||||
|
jsonObject.releaseTag,
|
||||||
|
);
|
||||||
|
if (deserializedReleaseTag === undefined) {
|
||||||
|
throw new Error(`Failed to deserialize release tag ${JSON.stringify(jsonObject.releaseTag)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.releaseTag = deserializedReleaseTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get releaseTag(): ReleaseTag {
|
||||||
|
return this[_releaseTag];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiReleaseTagMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.releaseTag = ReleaseTag[this.releaseTag];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiReleaseTagMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiReleaseTagMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiReleaseTagMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiReleaseTagMixin {
|
||||||
|
return apiItem.hasOwnProperty(_releaseTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
125
packages/api-extractor-model/src/mixins/ApiReturnTypeMixin.ts
Normal file
125
packages/api-extractor-model/src/mixins/ApiReturnTypeMixin.ts
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import { ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import type { IExcerptTokenRange, Excerpt } from './Excerpt.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiReturnTypeMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiReturnTypeMixinOptions extends IApiItemOptions {
|
||||||
|
returnTypeTokenRange: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiReturnTypeMixinJson extends IApiItemJson {
|
||||||
|
returnTypeTokenRange: IExcerptTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _returnTypeExcerpt: unique symbol = Symbol('ApiReturnTypeMixin._returnTypeExcerpt');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that are functions that return a value.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiReturnTypeMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* An {@link Excerpt} that describes the type of the function's return value.
|
||||||
|
*/
|
||||||
|
readonly returnTypeExcerpt: Excerpt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiReturnTypeMixinJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiReturnTypeMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiReturnTypeMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiReturnTypeMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiReturnTypeMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiReturnTypeMixin {
|
||||||
|
public [_returnTypeExcerpt]: Excerpt;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiReturnTypeMixinOptions = args[0];
|
||||||
|
|
||||||
|
if (this instanceof ApiDeclaredItem) {
|
||||||
|
this[_returnTypeExcerpt] = this.buildExcerpt(options.returnTypeTokenRange);
|
||||||
|
} else {
|
||||||
|
throw new InternalError('ApiReturnTypeMixin expects a base class that inherits from ApiDeclaredItem');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiReturnTypeMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiReturnTypeMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.returnTypeTokenRange = jsonObject.returnTypeTokenRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get returnTypeExcerpt(): Excerpt {
|
||||||
|
return this[_returnTypeExcerpt];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiReturnTypeMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.returnTypeTokenRange = this.returnTypeExcerpt.tokenRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiReturnTypeMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiReturnTypeMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiReturnTypeMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiReturnTypeMixin {
|
||||||
|
return apiItem.hasOwnProperty(_returnTypeExcerpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
117
packages/api-extractor-model/src/mixins/ApiStaticMixin.ts
Normal file
117
packages/api-extractor-model/src/mixins/ApiStaticMixin.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (IApiStaticMixinOptions:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiStaticMixinOptions extends IApiItemOptions {
|
||||||
|
isStatic: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiStaticMixinJson extends IApiItemJson {
|
||||||
|
isStatic: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _isStatic: unique symbol = Symbol('ApiStaticMixin._isStatic');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can have the TypeScript `static` keyword applied to them.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiStaticMixin extends ApiItem {
|
||||||
|
/**
|
||||||
|
* Whether the declaration has the TypeScript `static` keyword.
|
||||||
|
*/
|
||||||
|
readonly isStatic: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiStaticMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiStaticMixin:interface)} functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiStaticMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiStaticMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiStaticMixin {
|
||||||
|
public [_isStatic]: boolean;
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiStaticMixinOptions = args[0];
|
||||||
|
this[_isStatic] = options.isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiStaticMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiStaticMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.isStatic = jsonObject.isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isStatic(): boolean {
|
||||||
|
return this[_isStatic];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiStaticMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
jsonObject.isStatic = this.isStatic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiStaticMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiStaticMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiStaticMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiStaticMixin {
|
||||||
|
return apiItem.hasOwnProperty(_isStatic);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import { InternalError } from '@rushstack/node-core-library';
|
||||||
|
import { ApiDeclaredItem } from '../items/ApiDeclaredItem.js';
|
||||||
|
import type { ApiItem, IApiItemJson, IApiItemConstructor, IApiItemOptions } from '../items/ApiItem.js';
|
||||||
|
import type { DeserializerContext } from '../model/DeserializerContext.js';
|
||||||
|
import { TypeParameter } from '../model/TypeParameter.js';
|
||||||
|
import type { Excerpt, IExcerptTokenRange } from './Excerpt.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents parameter information that is part of {@link IApiTypeParameterListMixinOptions}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiTypeParameterOptions {
|
||||||
|
constraintTokenRange: IExcerptTokenRange;
|
||||||
|
defaultTypeTokenRange: IExcerptTokenRange;
|
||||||
|
typeParameterName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor options for {@link (ApiTypeParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IApiTypeParameterListMixinOptions extends IApiItemOptions {
|
||||||
|
typeParameters: IApiTypeParameterOptions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiTypeParameterListMixinJson extends IApiItemJson {
|
||||||
|
typeParameters: IApiTypeParameterOptions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const _typeParameters: unique symbol = Symbol('ApiTypeParameterListMixin._typeParameters');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mixin base class for API items that can have type parameters.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
|
* API declarations. The non-abstract classes (e.g. `ApiClass`, `ApiEnum`, `ApiInterface`, etc.) use
|
||||||
|
* TypeScript "mixin" functions (e.g. `ApiDeclaredItem`, `ApiItemContainerMixin`, etc.) to add various
|
||||||
|
* features that cannot be represented as a normal inheritance chain (since TypeScript does not allow a child class
|
||||||
|
* to extend more than one base class). The "mixin" is a TypeScript merged declaration with three components:
|
||||||
|
* the function that generates a subclass, an interface that describes the members of the subclass, and
|
||||||
|
* a namespace containing static members of the class.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ApiTypeParameterListMixin extends ApiItem {
|
||||||
|
serializeInto(jsonObject: Partial<IApiItemJson>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type parameters.
|
||||||
|
*/
|
||||||
|
readonly typeParameters: readonly TypeParameter[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin function for {@link (ApiTypeParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @param baseClass - The base class to be extended
|
||||||
|
* @returns A child class that extends baseClass, adding the {@link (ApiTypeParameterListMixin:interface)}
|
||||||
|
* functionality.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function ApiTypeParameterListMixin<TBaseClass extends IApiItemConstructor>(
|
||||||
|
baseClass: TBaseClass,
|
||||||
|
): TBaseClass & (new (...args: any[]) => ApiTypeParameterListMixin) {
|
||||||
|
class MixedClass extends baseClass implements ApiTypeParameterListMixin {
|
||||||
|
public readonly [_typeParameters]: TypeParameter[];
|
||||||
|
|
||||||
|
public constructor(...args: any[]) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
const options: IApiTypeParameterListMixinOptions = args[0];
|
||||||
|
|
||||||
|
this[_typeParameters] = [];
|
||||||
|
|
||||||
|
if (this instanceof ApiDeclaredItem) {
|
||||||
|
if (options.typeParameters) {
|
||||||
|
for (const typeParameterOptions of options.typeParameters) {
|
||||||
|
const defaultTypeExcerpt: Excerpt = this.buildExcerpt(typeParameterOptions.defaultTypeTokenRange);
|
||||||
|
const typeParameter: TypeParameter = new TypeParameter({
|
||||||
|
name: typeParameterOptions.typeParameterName,
|
||||||
|
constraintExcerpt: this.buildExcerpt(typeParameterOptions.constraintTokenRange),
|
||||||
|
defaultTypeExcerpt,
|
||||||
|
isOptional: !defaultTypeExcerpt.isEmpty,
|
||||||
|
parent: this,
|
||||||
|
});
|
||||||
|
|
||||||
|
this[_typeParameters].push(typeParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InternalError('ApiTypeParameterListMixin expects a base class that inherits from ApiDeclaredItem');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public static override onDeserializeInto(
|
||||||
|
options: Partial<IApiTypeParameterListMixinOptions>,
|
||||||
|
context: DeserializerContext,
|
||||||
|
jsonObject: IApiTypeParameterListMixinJson,
|
||||||
|
): void {
|
||||||
|
baseClass.onDeserializeInto(options, context, jsonObject);
|
||||||
|
|
||||||
|
options.typeParameters = jsonObject.typeParameters || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get typeParameters(): readonly TypeParameter[] {
|
||||||
|
return this[_typeParameters];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public override serializeInto(jsonObject: Partial<IApiTypeParameterListMixinJson>): void {
|
||||||
|
super.serializeInto(jsonObject);
|
||||||
|
|
||||||
|
const typeParameterObjects: IApiTypeParameterOptions[] = [];
|
||||||
|
for (const typeParameter of this.typeParameters) {
|
||||||
|
typeParameterObjects.push({
|
||||||
|
typeParameterName: typeParameter.name,
|
||||||
|
constraintTokenRange: typeParameter.constraintExcerpt.tokenRange,
|
||||||
|
defaultTypeTokenRange: typeParameter.defaultTypeExcerpt.tokenRange,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeParameterObjects.length > 0) {
|
||||||
|
jsonObject.typeParameters = typeParameterObjects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MixedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static members for {@link (ApiTypeParameterListMixin:interface)}.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export namespace ApiTypeParameterListMixin {
|
||||||
|
/**
|
||||||
|
* A type guard that tests whether the specified `ApiItem` subclass extends the `ApiParameterListMixin` mixin.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* The JavaScript `instanceof` operator cannot be used to test for mixin inheritance, because each invocation of
|
||||||
|
* the mixin function produces a different subclass. (This could be mitigated by `Symbol.hasInstance`, however
|
||||||
|
* the TypeScript type system cannot invoke a runtime test.)
|
||||||
|
*/
|
||||||
|
export function isBaseClassOf(apiItem: ApiItem): apiItem is ApiTypeParameterListMixin {
|
||||||
|
return apiItem.hasOwnProperty(_typeParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
173
packages/api-extractor-model/src/mixins/Excerpt.ts
Normal file
173
packages/api-extractor-model/src/mixins/Excerpt.ts
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference';
|
||||||
|
import { Text } from '@rushstack/node-core-library';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export enum ExcerptTokenKind {
|
||||||
|
/**
|
||||||
|
* Generic text without any special properties
|
||||||
|
*/
|
||||||
|
Content = 'Content',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to an API declaration
|
||||||
|
*/
|
||||||
|
Reference = 'Reference',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@link Excerpt} to indicate a range of indexes within an array of `ExcerptToken` objects.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IExcerptTokenRange {
|
||||||
|
/**
|
||||||
|
* The index of the last member of the span, plus one.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
*
|
||||||
|
* If `startIndex` and `endIndex` are the same number, then the span is empty.
|
||||||
|
*/
|
||||||
|
endIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The starting index of the span.
|
||||||
|
*/
|
||||||
|
startIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IExcerptToken {
|
||||||
|
canonicalReference?: string | undefined;
|
||||||
|
readonly kind: ExcerptTokenKind;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a fragment of text belonging to an {@link Excerpt} object.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class ExcerptToken {
|
||||||
|
private readonly _kind: ExcerptTokenKind;
|
||||||
|
|
||||||
|
private readonly _text: string;
|
||||||
|
|
||||||
|
private readonly _canonicalReference: DeclarationReference | undefined;
|
||||||
|
|
||||||
|
public constructor(kind: ExcerptTokenKind, text: string, canonicalReference?: DeclarationReference) {
|
||||||
|
this._kind = kind;
|
||||||
|
|
||||||
|
// Standardize the newlines across operating systems. Even though this may deviate from the actual
|
||||||
|
// input source file that was parsed, it's useful because the newline gets serialized inside
|
||||||
|
// a string literal in .api.json, which cannot be automatically normalized by Git.
|
||||||
|
this._text = Text.convertToLf(text);
|
||||||
|
this._canonicalReference = canonicalReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the kind of token.
|
||||||
|
*/
|
||||||
|
public get kind(): ExcerptTokenKind {
|
||||||
|
return this._kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text fragment.
|
||||||
|
*/
|
||||||
|
public get text(): string {
|
||||||
|
return this._text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hyperlink target for a token whose type is `ExcerptTokenKind.Reference`. For other token types,
|
||||||
|
* this property will be `undefined`.
|
||||||
|
*/
|
||||||
|
public get canonicalReference(): DeclarationReference | undefined {
|
||||||
|
return this._canonicalReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `Excerpt` class is used by {@link ApiDeclaredItem} to represent a TypeScript code fragment that may be
|
||||||
|
* annotated with hyperlinks to declared types (and in the future, source code locations).
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* API Extractor's .api.json file format stores excerpts compactly as a start/end indexes into an array of tokens.
|
||||||
|
* Every `ApiDeclaredItem` has a "main excerpt" corresponding to the full list of tokens. The declaration may
|
||||||
|
* also have have "captured" excerpts that correspond to subranges of tokens.
|
||||||
|
*
|
||||||
|
* For example, if the main excerpt is:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* function parse(s: string): Vector | undefined;
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ...then this entire signature is the "main excerpt", whereas the function's return type `Vector | undefined` is a
|
||||||
|
* captured excerpt. The `Vector` token might be a hyperlink to that API item.
|
||||||
|
*
|
||||||
|
* An excerpt may be empty (i.e. a token range containing zero tokens). For example, if a function's return value
|
||||||
|
* is not explicitly declared, then the returnTypeExcerpt will be empty. By contrast, a class constructor cannot
|
||||||
|
* have a return value, so ApiConstructor has no returnTypeExcerpt property at all.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class Excerpt {
|
||||||
|
/**
|
||||||
|
* The complete list of tokens for the source code fragment that this excerpt is based upon.
|
||||||
|
* If this object is the main excerpt, then it will span all of the tokens; otherwise, it will correspond to
|
||||||
|
* a range within the array.
|
||||||
|
*/
|
||||||
|
public readonly tokens: readonly ExcerptToken[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the excerpt's range within the `tokens` array.
|
||||||
|
*/
|
||||||
|
public readonly tokenRange: Readonly<IExcerptTokenRange>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tokens spanned by this excerpt. It is the range of the `tokens` array as specified by the `tokenRange`
|
||||||
|
* property.
|
||||||
|
*/
|
||||||
|
public readonly spannedTokens: readonly ExcerptToken[];
|
||||||
|
|
||||||
|
private _text: string | undefined;
|
||||||
|
|
||||||
|
public constructor(tokens: readonly ExcerptToken[], tokenRange: IExcerptTokenRange) {
|
||||||
|
this.tokens = tokens;
|
||||||
|
this.tokenRange = tokenRange;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.tokenRange.startIndex < 0 ||
|
||||||
|
this.tokenRange.endIndex > this.tokens.length ||
|
||||||
|
this.tokenRange.startIndex > this.tokenRange.endIndex
|
||||||
|
) {
|
||||||
|
throw new Error('Invalid token range');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.spannedTokens = this.tokens.slice(this.tokenRange.startIndex, this.tokenRange.endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The excerpted text, formed by concatenating the text of the `spannedTokens` strings.
|
||||||
|
*/
|
||||||
|
public get text(): string {
|
||||||
|
if (this._text === undefined) {
|
||||||
|
this._text = this.spannedTokens.map((x) => x.text).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the excerpt is an empty range.
|
||||||
|
*/
|
||||||
|
public get isEmpty(): boolean {
|
||||||
|
return this.tokenRange.startIndex === this.tokenRange.endIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
import type { ApiItem } from '../items/ApiItem.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic result object for finding API items used by different kinds of find operations.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IFindApiItemsResult {
|
||||||
|
/**
|
||||||
|
* The API items that were found. Not guaranteed to be complete, see `maybeIncompleteResult`.
|
||||||
|
*/
|
||||||
|
items: ApiItem[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the result is potentially incomplete due to errors during the find operation.
|
||||||
|
* If true, the `messages` explain the errors in more detail.
|
||||||
|
*/
|
||||||
|
maybeIncompleteResult: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnostic messages regarding the find operation.
|
||||||
|
*/
|
||||||
|
messages: IFindApiItemsMessage[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object is used for messages returned as part of `IFindApiItemsResult`.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface IFindApiItemsMessage {
|
||||||
|
/**
|
||||||
|
* Unique identifier for the message.
|
||||||
|
*
|
||||||
|
* @beta
|
||||||
|
*/
|
||||||
|
messageId: FindApiItemsMessageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text description of the message.
|
||||||
|
*/
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifiers for messages returned as part of `IFindApiItemsResult`.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export enum FindApiItemsMessageId {
|
||||||
|
/**
|
||||||
|
* "Unable to resolve declaration reference within API item ___: ___"
|
||||||
|
*/
|
||||||
|
DeclarationResolutionFailed = 'declaration-resolution-failed',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Unable to analyze extends clause ___ of API item ___ because no canonical reference was found."
|
||||||
|
*/
|
||||||
|
ExtendsClauseMissingReference = 'extends-clause-missing-reference',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Unable to analyze references of API item ___ because it is not associated with an ApiModel"
|
||||||
|
*/
|
||||||
|
NoAssociatedApiModel = 'no-associated-api-model',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Unable to analyze references of API item ___ because it is of unsupported kind ___"
|
||||||
|
*/
|
||||||
|
UnsupportedKind = 'unsupported-kind',
|
||||||
|
}
|
||||||
18
packages/api-extractor-model/src/mixins/Mixin.ts
Normal file
18
packages/api-extractor-model/src/mixins/Mixin.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||||
|
// See LICENSE in the project root for license information.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstraction is used by the mixin pattern.
|
||||||
|
* It describes a class constructor.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export type Constructor<T = {}> = new (...args: any[]) => T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstraction is used by the mixin pattern.
|
||||||
|
* It describes the "static side" of a class.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export type PropertiesOf<T> = { [K in keyof T]: T[K] };
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user