Skip to content

Commit

Permalink
Merge branch 'main' into fix/threads-fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
didinele authored Nov 5, 2024
2 parents 31bfb5b + 939e364 commit 4d0b99d
Show file tree
Hide file tree
Showing 41 changed files with 783 additions and 298 deletions.
2 changes: 1 addition & 1 deletion .github/.kodiak.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version = 1

[merge]
require_automerge_label = false
blocking_labels = ['blocked', 'in review']
blocking_labels = ['blocked', 'in review', 'semver:major']
method = 'squash'

[merge.message]
Expand Down
1 change: 1 addition & 0 deletions apps/website/src/components/ParameterNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export async function ParameterNode({
{description ? <Badges node={parameter} /> : null}
{parameter.name}
{parameter.isOptional ? '?' : ''}: <ExcerptNode node={parameter.typeExcerpt} version={version} />
{parameter.defaultValue ? ` = ${parameter.defaultValue}` : ''}
</span>
{description && parameter.description?.length ? (
<div className="mt-4 pl-4">
Expand Down
8 changes: 7 additions & 1 deletion apps/website/src/components/PropertyNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ export async function PropertyNode({
<LinkIcon aria-hidden size={16} />
</Link>
{property.displayName}
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />{' '}
{property.summary?.defaultValueBlock.length
? `= ${property.summary.defaultValueBlock.reduce(
(acc: string, def: { kind: string; text: string }) => `${acc}${def.text}`,
'',
)}`
: ''}
</span>
</h3>

Expand Down
114 changes: 86 additions & 28 deletions packages/api-extractor-model/src/mixins/ApiItemContainerMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
// 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 {
type DocNode,
type DocPlainText,
DocDeclarationReference,
DocNodeKind,
TSDocConfiguration,
DocMemberReference,
DocMemberIdentifier,
} from '@microsoft/tsdoc';
import type { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
import { InternalError } from '@rushstack/node-core-library';
import type { IExcerptToken, IExcerptTokenRange } from '../index.js';
Expand Down Expand Up @@ -42,6 +50,11 @@ export interface IApiItemContainerJson extends IApiItemJson {
preserveMemberOrder?: boolean;
}

interface Mixin {
declarationReference: DocDeclarationReference;
typeParameters: IExcerptTokenRange[];
}

interface ExcerptTokenRangeInDeclaredItem {
item: ApiDeclaredItem;
range: IExcerptTokenRange;
Expand Down Expand Up @@ -393,14 +406,52 @@ export function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
}
}

const findPlainTextNode = (node: DocNode): DocPlainText | undefined => {
switch (node.kind) {
case DocNodeKind.PlainText:
return node as DocPlainText;
default:
for (const child of node.getChildNodes()) {
const result = findPlainTextNode(child);
if (result) return result;
}
}

return undefined;
};

// Interfaces can extend multiple interfaces, so iterate through all of them.
// Also Classes can have multiple mixins
const extendedItems: IMappedTypeParameters[] = [];
let extendsTypes: readonly HeritageType[] | undefined;
let extendsTypes: readonly (HeritageType | Mixin)[] | undefined;

switch (next.item.kind) {
case ApiItemKind.Class: {
const apiClass: ApiClass = next.item as ApiClass;
extendsTypes = apiClass.extendsType ? [apiClass.extendsType] : [];
const configuration = apiClass.tsdocComment?.configuration ?? new TSDocConfiguration();
const mixins =
apiClass.tsdocComment?.customBlocks
.filter(
(block) => block.blockTag.tagName === '@mixes', // &&
// block.getChildNodes().some((node) => node.kind === DocNodeKind.PlainText),
)
.map(findPlainTextNode)
.filter((block) => block !== undefined)
.map((block) => ({
declarationReference: new DocDeclarationReference({
configuration,
memberReferences: block.text.split('.').map(
(part, index) =>
new DocMemberReference({
configuration,
hasDot: index > 0,
memberIdentifier: new DocMemberIdentifier({ configuration, identifier: part }),
}),
),
}),
typeParameters: [] as IExcerptTokenRange[],
})) ?? [];
extendsTypes = apiClass.extendsType ? [apiClass.extendsType, ...mixins] : [...mixins];
break;
}

Expand All @@ -425,30 +476,38 @@ export function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
}

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;
},
);
let canonicalReference: DeclarationReference | DocDeclarationReference;
if ('excerpt' in extendsType) {
// 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.item.displayName} because no canonical reference was found`,
});
maybeIncompleteResult = true;
continue;
}

if (!firstReferenceToken) {
messages.push({
messageId: FindApiItemsMessageId.ExtendsClauseMissingReference,
text: `Unable to analyze extends clause ${extendsType.excerpt.text} of API item ${next.item.displayName} because no canonical reference was found`,
});
maybeIncompleteResult = true;
continue;
canonicalReference = firstReferenceToken.canonicalReference!;
} else {
// extendsType is a Mixin
canonicalReference = extendsType.declarationReference;
}

const apiModel: ApiModel | undefined = this.getAssociatedModel();
Expand All @@ -461,10 +520,9 @@ export function ApiItemContainerMixin<TBaseClass extends IApiItemConstructor>(
continue;
}

const canonicalReference: DeclarationReference = firstReferenceToken.canonicalReference!;
const apiItemResult: IResolveDeclarationReferenceResult = apiModel.resolveDeclarationReference(
canonicalReference,
undefined,
this,
);

const apiItem: ApiItem | undefined = apiItemResult.resolvedApiItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { IExcerptTokenRange } from './Excerpt.js';
* @public
*/
export interface IApiParameterOptions {
defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
parameterName: string;
Expand Down Expand Up @@ -124,6 +125,7 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
isOptional: Boolean(parameterOptions.isOptional),
isRest: Boolean(parameterOptions.isRest),
parent: this,
defaultValue: parameterOptions.defaultValue,
});

this[_parameters].push(parameter);
Expand Down Expand Up @@ -171,6 +173,7 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
isOptional: parameter.isOptional,
isRest: parameter.isRest,
defaultValue: parameter.defaultValue,
});
}

Expand Down
11 changes: 10 additions & 1 deletion packages/api-extractor-model/src/model/ApiPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const MinifyJSONMapping = {
constraintTokenRange: 'ctr',
dependencies: 'dp',
defaultTypeTokenRange: 'dtr',
defaultValue: 'dv',
docComment: 'd',
endIndex: 'en',
excerptTokens: 'ex',
Expand Down Expand Up @@ -293,7 +294,11 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented

const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();

if (versionToDeserialize >= ApiJsonSchemaVersion.V_1004 && 'tsdocConfiguration' in jsonObject) {
if (
versionToDeserialize >= ApiJsonSchemaVersion.V_1004 &&
'tsdocConfig' in jsonObject.metadata &&
'$schema' in jsonObject.metadata.tsdocConfig
) {
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromObject(jsonObject.metadata.tsdocConfig);
if (tsdocConfigFile.hasErrors) {
throw new Error(`Error loading ${apiJsonFilename}:\n` + tsdocConfigFile.getErrorSummary());
Expand Down Expand Up @@ -420,6 +425,8 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
for (const key of Object.keys(item)) {
if (key === 'dependencies') {
result[MinifyJSONMapping.dependencies] = item.dependencies;
} else if (key === 'tsdocConfig') {
result[MinifyJSONMapping.tsdocConfig] = item.tsdocConfig;
} else
result[MinifyJSONMapping[key as keyof typeof MinifyJSONMapping]] =
typeof item[key] === 'object' ? mapper(item[key]) : item[key];
Expand All @@ -440,6 +447,8 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
for (const key of Object.keys(item)) {
if (key === MinifyJSONMapping.dependencies) {
result.dependencies = item[MinifyJSONMapping.dependencies];
} else if (key === MinifyJSONMapping.tsdocConfig) {
result.tsdocConfig = item[MinifyJSONMapping.tsdocConfig];
} else
result[
Object.keys(MinifyJSONMapping).find(
Expand Down
1 change: 1 addition & 0 deletions packages/api-extractor-model/src/model/Deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ function mapParam(
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
},
defaultValue: param.default,
};
}

Expand Down
7 changes: 7 additions & 0 deletions packages/api-extractor-model/src/model/Parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { Excerpt } from '../mixins/Excerpt.js';
* @public
*/
export interface IParameterOptions {
defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
name: string;
Expand Down Expand Up @@ -56,6 +57,11 @@ export class Parameter {
*/
public isRest: boolean;

/**
* The default value for this parameter if optional
*/
public defaultValue: string | undefined;

private readonly _parent: ApiParameterListMixin;

public constructor(options: IParameterOptions) {
Expand All @@ -64,6 +70,7 @@ export class Parameter {
this.isOptional = options.isOptional;
this.isRest = options.isRest;
this._parent = options.parent;
this.defaultValue = options.defaultValue;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/api-extractor/extends/tsdoc-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
{
"tagName": "@preapproved",
"syntaxKind": "modifier"
},
{
"tagName": "@mixes",
"syntaxKind": "block"
}
],

Expand Down
Loading

0 comments on commit 4d0b99d

Please sign in to comment.